Compare commits
111 Commits
Author | SHA1 | Date | |
---|---|---|---|
cb8e9fdd36 | |||
53ce3c1526 | |||
a78f06b41b | |||
ce7ef30806 | |||
fd93c0776a | |||
6a762c6c0e | |||
23c5aef276 | |||
69707a7207 | |||
cfd3505414 | |||
ee958dc351 | |||
680f2325a3 | |||
2f0ad3eeb2 | |||
c895a9c7d9 | |||
388a8404f5 | |||
320cb1c418 | |||
8a6b73915f | |||
774355d608 | |||
35dbce3a68 | |||
6d0a267ba4 | |||
df701be572 | |||
1edad47e6e | |||
c873abfe18 | |||
989446ef36 | |||
fc6daed620 | |||
5e921f1dfc | |||
45bbf1b693 | |||
8b8c664f0f | |||
079334f71b | |||
3fe0c76d54 | |||
1e55a3e6a8 | |||
950a2f8b53 | |||
bbe2e1e46e | |||
635c58c131 | |||
ba39d806b7 | |||
355e97cb5e | |||
4339f8cfc0 | |||
448572d7a1 | |||
2132c7b6da | |||
d0bd83d6c5 | |||
1037b7c23d | |||
df197f73ea | |||
ea08f603f5 | |||
fa2f1235f7 | |||
ff5d02c964 | |||
e93d6799fd | |||
f2027230a0 | |||
cb47d4f772 | |||
eebc9fbcfa | |||
0e698491f3 | |||
ae52e8fabb | |||
ccd655ef8b | |||
3dc6e71aaf | |||
e6d3577f74 | |||
ef05024f2f | |||
d3bc784248 | |||
979701331e | |||
76b1682296 | |||
7c31b72f99 | |||
f7c2072cff | |||
392db1cd11 | |||
ca244bcfe1 | |||
2d02f51f25 | |||
592fb5ca9f | |||
a3945bc7f1 | |||
2adde9830c | |||
0355afe11c | |||
998fe3f370 | |||
eb71fc20e6 | |||
ab348bd5f9 | |||
c518d1c6c7 | |||
d8d16b4a7d | |||
928e4b9bc2 | |||
4f900d6566 | |||
362a997187 | |||
89c658746d | |||
75d699f7ef | |||
f7412690b6 | |||
ece2b23407 | |||
f84af9a44b | |||
90dc1103f6 | |||
c469fb24db | |||
32be6e36da | |||
b34ad22ad6 | |||
2358139a6b | |||
43ebfe7a2f | |||
0b8094dea8 | |||
f1d1570b10 | |||
e9e68bc802 | |||
4c369510ce | |||
96413d6c47 | |||
df6c7cf19f | |||
49fc28d86c | |||
cc67a83ce8 | |||
742e2b5089 | |||
d19ff1e300 | |||
01950ed443 | |||
cf1689a3c2 | |||
66d0bab0a5 | |||
5889f20f1e | |||
ebec10e312 | |||
ae8a0c7fd0 | |||
bb49200fad | |||
a6bba0bc6c | |||
fb08f79344 | |||
741c74825e | |||
28539cd47b | |||
8ca7c5a343 | |||
32b56e7071 | |||
7dad717952 | |||
34e928755f | |||
51e0f311fe |
13
.editorconfig
Normal file
13
.editorconfig
Normal file
@ -0,0 +1,13 @@
|
|||||||
|
# Editor configuration, see http://editorconfig.org
|
||||||
|
root = true
|
||||||
|
|
||||||
|
[*]
|
||||||
|
charset = utf-8
|
||||||
|
indent_style = space
|
||||||
|
indent_size = 4
|
||||||
|
insert_final_newline = true
|
||||||
|
trim_trailing_whitespace = true
|
||||||
|
|
||||||
|
[*.md]
|
||||||
|
max_line_length = off
|
||||||
|
trim_trailing_whitespace = false
|
12
.gitignore
vendored
12
.gitignore
vendored
@ -36,5 +36,13 @@ node_modules
|
|||||||
build
|
build
|
||||||
build-tests
|
build-tests
|
||||||
|
|
||||||
# vscode
|
# VSCode
|
||||||
.vscode
|
.vscode/*
|
||||||
|
!.vscode/settings.json
|
||||||
|
!.vscode/tasks.json
|
||||||
|
!.vscode/launch.json
|
||||||
|
!.vscode/extensions.json
|
||||||
|
.history
|
||||||
|
|
||||||
|
# Lock files
|
||||||
|
package-lock.json
|
||||||
|
@ -6,6 +6,15 @@ install:
|
|||||||
script:
|
script:
|
||||||
- npm run lint
|
- npm run lint
|
||||||
- npm test
|
- npm test
|
||||||
|
- npm run style
|
||||||
|
- npm run build
|
||||||
|
- node ./demo/demo1.js
|
||||||
|
- node ./demo/demo2.js
|
||||||
|
- node ./demo/demo3.js
|
||||||
|
- node ./demo/demo4.js
|
||||||
|
- node ./demo/demo5.js
|
||||||
|
- node ./demo/demo6.js
|
||||||
|
- node ./demo/demo7.js
|
||||||
after_failure:
|
after_failure:
|
||||||
- "cat /home/travis/builds/dolanmiu/docx/npm-debug.log"
|
- "cat /home/travis/builds/dolanmiu/docx/npm-debug.log"
|
||||||
after_success:
|
after_success:
|
||||||
|
9
.vscode/settings.json
vendored
Normal file
9
.vscode/settings.json
vendored
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
{
|
||||||
|
"cSpell.words": ["clippy", "docx", "dolan", "miu", "officegen", "typedoc"],
|
||||||
|
"prettier.trailingComma": "all",
|
||||||
|
"prettier.printWidth": 140,
|
||||||
|
"editor.formatOnSave": false,
|
||||||
|
"prettier.tabWidth": 4,
|
||||||
|
"prettier.arrowParens": "always",
|
||||||
|
"prettier.bracketSpacing": true
|
||||||
|
}
|
12
README.md
12
README.md
@ -8,7 +8,12 @@
|
|||||||
|
|
||||||
-----
|
-----
|
||||||
|
|
||||||
[![NPM version][npm-image]][npm-url] [![Build Status][travis-image]][travis-url] [![Dependency Status][gemnasium-image]][gemnasium-url] [![Known Vulnerabilities][snky-image]][snky-url] [![Chat on Gitter][gitter-image]][gitter-url]
|
[![NPM version][npm-image]][npm-url]
|
||||||
|
[![Build Status][travis-image]][travis-url]
|
||||||
|
[![Dependency Status][gemnasium-image]][gemnasium-url]
|
||||||
|
[![Known Vulnerabilities][snky-image]][snky-url]
|
||||||
|
[![Chat on Gitter][gitter-image]][gitter-url]
|
||||||
|
[![code style: prettier][prettier-image]][prettier-url]
|
||||||
|
|
||||||
[](https://nodei.co/npm/docx/)
|
[](https://nodei.co/npm/docx/)
|
||||||
|
|
||||||
@ -57,6 +62,8 @@ var exporter = new docx.LocalPacker(doc);
|
|||||||
var exporter = new docx.ExpressPacker(doc, res);
|
var exporter = new docx.ExpressPacker(doc, res);
|
||||||
|
|
||||||
exporter.pack('My First Document');
|
exporter.pack('My First Document');
|
||||||
|
// If you want to export it as a .pdf file instead
|
||||||
|
exporter.packPdf('My First Document');
|
||||||
|
|
||||||
// done! A file called 'My First Document.docx'
|
// done! A file called 'My First Document.docx'
|
||||||
// will be in your file system if you used LocalPacker
|
// will be in your file system if you used LocalPacker
|
||||||
@ -88,4 +95,5 @@ Huge thanks to [@felipeochoa](https://github.com/felipeochoa) for awesome contri
|
|||||||
[gitter-url]: https://gitter.im/docx-lib/Lobby
|
[gitter-url]: https://gitter.im/docx-lib/Lobby
|
||||||
[gemnasium-image]: https://gemnasium.com/badges/github.com/dolanmiu/docx.svg
|
[gemnasium-image]: https://gemnasium.com/badges/github.com/dolanmiu/docx.svg
|
||||||
[gemnasium-url]: https://gemnasium.com/github.com/dolanmiu/docx
|
[gemnasium-url]: https://gemnasium.com/github.com/dolanmiu/docx
|
||||||
|
[prettier-image]: https://img.shields.io/badge/code_style-prettier-ff69b4.svg
|
||||||
|
[prettier-url]: https://github.com/prettier/prettier
|
||||||
|
@ -10,13 +10,7 @@ paragraph.addRun(dateText);
|
|||||||
|
|
||||||
doc.addParagraph(paragraph);
|
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);
|
var exporter = new docx.LocalPacker(doc);
|
||||||
exporter.pack('My Document');
|
exporter.pack('My Document');
|
||||||
|
|
||||||
console.log('Document created succesfully at project root!');
|
console.log('Document created successfully at project root!');
|
||||||
|
@ -1,7 +1,12 @@
|
|||||||
const docx = require('../build');
|
const docx = require('../build');
|
||||||
|
|
||||||
const styles = new docx.Styles();
|
const doc = new docx.Document({
|
||||||
styles.createParagraphStyle('Heading1', 'Heading 1')
|
creator: 'Clippy',
|
||||||
|
title: 'Sample Document',
|
||||||
|
description: 'A brief example of using docx',
|
||||||
|
});
|
||||||
|
|
||||||
|
doc.Styles.createParagraphStyle('Heading1', 'Heading 1')
|
||||||
.basedOn("Normal")
|
.basedOn("Normal")
|
||||||
.next("Normal")
|
.next("Normal")
|
||||||
.quickFormat()
|
.quickFormat()
|
||||||
@ -10,7 +15,7 @@ styles.createParagraphStyle('Heading1', 'Heading 1')
|
|||||||
.italics()
|
.italics()
|
||||||
.spacing({after: 120});
|
.spacing({after: 120});
|
||||||
|
|
||||||
styles.createParagraphStyle('Heading2', 'Heading 2')
|
doc.Styles.createParagraphStyle('Heading2', 'Heading 2')
|
||||||
.basedOn("Normal")
|
.basedOn("Normal")
|
||||||
.next("Normal")
|
.next("Normal")
|
||||||
.quickFormat()
|
.quickFormat()
|
||||||
@ -19,7 +24,7 @@ styles.createParagraphStyle('Heading2', 'Heading 2')
|
|||||||
.underline('double', 'FF0000')
|
.underline('double', 'FF0000')
|
||||||
.spacing({before: 240, after: 120});
|
.spacing({before: 240, after: 120});
|
||||||
|
|
||||||
styles.createParagraphStyle('aside', 'Aside')
|
doc.Styles.createParagraphStyle('aside', 'Aside')
|
||||||
.basedOn('Normal')
|
.basedOn('Normal')
|
||||||
.next('Normal')
|
.next('Normal')
|
||||||
.color('999999')
|
.color('999999')
|
||||||
@ -27,31 +32,24 @@ styles.createParagraphStyle('aside', 'Aside')
|
|||||||
.indent(720)
|
.indent(720)
|
||||||
.spacing({line: 276});
|
.spacing({line: 276});
|
||||||
|
|
||||||
styles.createParagraphStyle('wellSpaced', 'Well Spaced')
|
doc.Styles.createParagraphStyle('wellSpaced', 'Well Spaced')
|
||||||
.basedOn('Normal')
|
.basedOn('Normal')
|
||||||
.spacing({line: 276, before: 20 * 72 * .1, after: 20 * 72 * .05});
|
.spacing({line: 276, before: 20 * 72 * .1, after: 20 * 72 * .05});
|
||||||
|
|
||||||
styles.createParagraphStyle('ListParagraph', 'List Paragraph')
|
doc.Styles.createParagraphStyle('ListParagraph', 'List Paragraph')
|
||||||
.quickFormat()
|
.quickFormat()
|
||||||
.basedOn('Normal');
|
.basedOn('Normal');
|
||||||
|
|
||||||
|
|
||||||
const numbering = new docx.Numbering();
|
const numberedAbstract = doc.Numbering.createAbstractNumbering();
|
||||||
const numberedAbstract = numbering.createAbstractNumbering();
|
|
||||||
numberedAbstract.createLevel(0, "lowerLetter", "%1)", "left");
|
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('Test heading1, bold and italicized').heading1();
|
||||||
doc.createParagraph('Some simple content');
|
doc.createParagraph('Some simple content');
|
||||||
doc.createParagraph('Test heading2 with double red underline').heading2();
|
doc.createParagraph('Test heading2 with double red underline').heading2();
|
||||||
|
|
||||||
const letterNumbering = numbering.createConcreteNumbering(numberedAbstract);
|
const letterNumbering = doc.Numbering.createConcreteNumbering(numberedAbstract);
|
||||||
const letterNumbering5 = numbering.createConcreteNumbering(numberedAbstract);
|
const letterNumbering5 = doc.Numbering.createConcreteNumbering(numberedAbstract);
|
||||||
letterNumbering5.overrideLevel(0, 5);
|
letterNumbering5.overrideLevel(0, 5);
|
||||||
|
|
||||||
doc.createParagraph('Option1').setNumbering(letterNumbering, 0);
|
doc.createParagraph('Option1').setNumbering(letterNumbering, 0);
|
||||||
@ -70,5 +68,7 @@ para.createTextRun(' switching to normal ');
|
|||||||
para.createTextRun('and then underlined ').underline();
|
para.createTextRun('and then underlined ').underline();
|
||||||
para.createTextRun('and back to normal.');
|
para.createTextRun('and back to normal.');
|
||||||
|
|
||||||
const exporter = new docx.LocalPacker(doc, styles, undefined, numbering);
|
const exporter = new docx.LocalPacker(doc);
|
||||||
exporter.pack('test.docx');
|
exporter.pack('My Document');
|
||||||
|
|
||||||
|
console.log('Document created successfully at project root!');
|
||||||
|
@ -32,4 +32,4 @@ doc.addParagraph(subSubP);
|
|||||||
var exporter = new docx.LocalPacker(doc);
|
var exporter = new docx.LocalPacker(doc);
|
||||||
exporter.pack('My Document');
|
exporter.pack('My Document');
|
||||||
|
|
||||||
console.log('Document created succesfully at project root!');
|
console.log('Document created successfully at project root!');
|
||||||
|
@ -9,4 +9,4 @@ table.getCell(2, 2).addContent(new docx.Paragraph('Hello'));
|
|||||||
var exporter = new docx.LocalPacker(doc);
|
var exporter = new docx.LocalPacker(doc);
|
||||||
exporter.pack('My Document');
|
exporter.pack('My Document');
|
||||||
|
|
||||||
console.log('Document created succesfully at project root!');
|
console.log('Document created successfully at project root!');
|
||||||
|
17
demo/demo5.js
Normal file
17
demo/demo5.js
Normal file
@ -0,0 +1,17 @@
|
|||||||
|
const docx = require('../build');
|
||||||
|
|
||||||
|
var doc = new docx.Document();
|
||||||
|
|
||||||
|
var paragraph = new docx.Paragraph("Hello World");
|
||||||
|
doc.addParagraph(paragraph);
|
||||||
|
|
||||||
|
const image = doc.createImage("./demo/images/image1.jpeg");
|
||||||
|
const image2 = doc.createImage("./demo/images/dog.png");
|
||||||
|
const image3 = doc.createImage("./demo/images/cat.jpg");
|
||||||
|
const image4 = doc.createImage("./demo/images/parrots.bmp");
|
||||||
|
const image5 = doc.createImage("./demo/images/pizza.gif");
|
||||||
|
|
||||||
|
var exporter = new docx.LocalPacker(doc);
|
||||||
|
exporter.pack('My Document');
|
||||||
|
|
||||||
|
console.log('Document created successfully at project root!');
|
25
demo/demo6.js
Normal file
25
demo/demo6.js
Normal file
@ -0,0 +1,25 @@
|
|||||||
|
const docx = require("../build");
|
||||||
|
|
||||||
|
var doc = new docx.Document(undefined, {
|
||||||
|
top: 0,
|
||||||
|
right: 0,
|
||||||
|
bottom: 0,
|
||||||
|
left: 0,
|
||||||
|
});
|
||||||
|
|
||||||
|
var paragraph = new docx.Paragraph("Hello World");
|
||||||
|
var institutionText = new docx.TextRun("University College London").bold();
|
||||||
|
var dateText = new docx.TextRun("5th Dec 2015").tab().bold();
|
||||||
|
paragraph.addRun(institutionText);
|
||||||
|
paragraph.addRun(dateText);
|
||||||
|
|
||||||
|
doc.addParagraph(paragraph);
|
||||||
|
|
||||||
|
doc.createParagraph("Hello World").heading1();
|
||||||
|
doc.createParagraph("University College London");
|
||||||
|
doc.createParagraph("5th Dec 2015");
|
||||||
|
|
||||||
|
var exporter = new docx.LocalPacker(doc);
|
||||||
|
exporter.pack("My Document");
|
||||||
|
|
||||||
|
console.log("Document created successfully at project root!");
|
14
demo/demo7.js
Normal file
14
demo/demo7.js
Normal file
@ -0,0 +1,14 @@
|
|||||||
|
const docx = require("../build");
|
||||||
|
|
||||||
|
var doc = new docx.Document(undefined, {
|
||||||
|
orientation: "landscape",
|
||||||
|
});
|
||||||
|
|
||||||
|
var paragraph = new docx.Paragraph("Hello World");
|
||||||
|
|
||||||
|
doc.addParagraph(paragraph);
|
||||||
|
|
||||||
|
var exporter = new docx.LocalPacker(doc);
|
||||||
|
exporter.pack("My Document");
|
||||||
|
|
||||||
|
console.log("Document created successfully at project root!");
|
13
demo/demo8.js
Normal file
13
demo/demo8.js
Normal file
@ -0,0 +1,13 @@
|
|||||||
|
const docx = require('../build');
|
||||||
|
|
||||||
|
var doc = new docx.Document();
|
||||||
|
|
||||||
|
doc.createParagraph("Hello World");
|
||||||
|
|
||||||
|
doc.Header.createParagraph("Header text");
|
||||||
|
doc.Footer.createParagraph("Footer text");
|
||||||
|
|
||||||
|
var exporter = new docx.LocalPacker(doc);
|
||||||
|
exporter.pack('My Document');
|
||||||
|
|
||||||
|
console.log('Document created successfully at project root!');
|
13
demo/demo9.js
Normal file
13
demo/demo9.js
Normal file
@ -0,0 +1,13 @@
|
|||||||
|
const docx = require('../build');
|
||||||
|
|
||||||
|
var doc = new docx.Document();
|
||||||
|
|
||||||
|
doc.createParagraph("Hello World");
|
||||||
|
|
||||||
|
doc.Header.createImage("./demo/images/pizza.gif");
|
||||||
|
doc.Footer.createImage("./demo/images/pizza.gif");
|
||||||
|
|
||||||
|
var exporter = new docx.LocalPacker(doc);
|
||||||
|
exporter.pack('My Document');
|
||||||
|
|
||||||
|
console.log('Document created successfully at project root!');
|
BIN
demo/images/cat.jpg
Normal file
BIN
demo/images/cat.jpg
Normal file
Binary file not shown.
After Width: | Height: | Size: 154 KiB |
BIN
demo/images/dog.png
Normal file
BIN
demo/images/dog.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 190 KiB |
Before Width: | Height: | Size: 162 KiB After Width: | Height: | Size: 162 KiB |
BIN
demo/images/parrots.bmp
Normal file
BIN
demo/images/parrots.bmp
Normal file
Binary file not shown.
After Width: | Height: | Size: 818 KiB |
BIN
demo/images/pizza.gif
Normal file
BIN
demo/images/pizza.gif
Normal file
Binary file not shown.
After Width: | Height: | Size: 310 KiB |
38
package.json
38
package.json
@ -1,19 +1,24 @@
|
|||||||
{
|
{
|
||||||
"name": "docx",
|
"name": "docx",
|
||||||
"version": "3.0.1",
|
"version": "3.2.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",
|
||||||
"test": "mocha ./build-tests --recursive",
|
"test": "mocha-webpack \"src/**/*.ts\"",
|
||||||
|
"test-watch": "mocha-webpack \"src/**/*.ts\" --watch",
|
||||||
"prepublishOnly": "npm run build",
|
"prepublishOnly": "npm run build",
|
||||||
"lint": "tslint --project ./ts",
|
"lint": "tslint --project .",
|
||||||
"build": "rimraf ./build && tsc -p ts",
|
"build": "npm run webpack && npm run fix-types",
|
||||||
|
"tsc": "rimraf ./build && tsc -p .",
|
||||||
|
"webpack": "rimraf ./build && webpack",
|
||||||
"demo": "npm run build && node ./demo",
|
"demo": "npm run build && node ./demo",
|
||||||
"typedoc": "typedoc --out docs/ ts/ --module commonjs --target ES6 --disableOutputCheck"
|
"typedoc": "npm run build && typedoc --out docs/ src/ --module commonjs --target ES6 --disableOutputCheck",
|
||||||
|
"style": "prettier -l --trailing-comma all --print-width 140 --arrow-parens always \"src/**/*.ts\"",
|
||||||
|
"fix-types": "node types-absolute-fixer.js"
|
||||||
},
|
},
|
||||||
"files": [
|
"files": [
|
||||||
"ts",
|
"src",
|
||||||
"build",
|
"build",
|
||||||
"template"
|
"template"
|
||||||
],
|
],
|
||||||
@ -35,9 +40,14 @@
|
|||||||
],
|
],
|
||||||
"types": "./build/index.d.ts",
|
"types": "./build/index.d.ts",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@types/archiver": "^1.3.4",
|
"@types/archiver": "^2.1.0",
|
||||||
"@types/express": "^4.0.35",
|
"@types/express": "^4.0.35",
|
||||||
"archiver": "^1.3.0",
|
"@types/image-size": "0.0.29",
|
||||||
|
"@types/request-promise": "^4.1.41",
|
||||||
|
"archiver": "^2.1.1",
|
||||||
|
"image-size": "^0.6.2",
|
||||||
|
"request": "^2.83.0",
|
||||||
|
"request-promise": "^4.2.2",
|
||||||
"xml": "^1.0.1"
|
"xml": "^1.0.1"
|
||||||
},
|
},
|
||||||
"author": "Dolan Miu",
|
"author": "Dolan Miu",
|
||||||
@ -49,13 +59,19 @@
|
|||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@types/chai": "^3.4.35",
|
"@types/chai": "^3.4.35",
|
||||||
"@types/mocha": "^2.2.39",
|
"@types/mocha": "^2.2.39",
|
||||||
|
"awesome-typescript-loader": "^3.4.1",
|
||||||
"chai": "^3.5.0",
|
"chai": "^3.5.0",
|
||||||
|
"glob": "^7.1.2",
|
||||||
"mocha": "^3.2.0",
|
"mocha": "^3.2.0",
|
||||||
|
"mocha-webpack": "^1.0.1",
|
||||||
|
"prettier": "^1.10.2",
|
||||||
"prompt": "^1.0.0",
|
"prompt": "^1.0.0",
|
||||||
|
"replace-in-file": "^3.1.0",
|
||||||
"rimraf": "^2.5.2",
|
"rimraf": "^2.5.2",
|
||||||
"shelljs": "^0.7.7",
|
"shelljs": "^0.7.7",
|
||||||
"tslint": "^5.1.0",
|
"tslint": "^5.1.0",
|
||||||
"typedoc": "^0.5.10",
|
"typedoc": "^0.9.0",
|
||||||
"typescript": "2.4.1"
|
"typescript": "2.6.2",
|
||||||
|
"webpack": "^3.10.0"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,9 +1,9 @@
|
|||||||
import { assert } from "chai";
|
import { assert } from "chai";
|
||||||
|
|
||||||
import * as docx from "../docx";
|
|
||||||
import { Attributes } from "../docx/xml-components";
|
|
||||||
import { Formatter } from "../export/formatter";
|
import { Formatter } from "../export/formatter";
|
||||||
import { Properties } from "../properties";
|
import * as file from "../file";
|
||||||
|
import { CoreProperties } from "../file/core-properties";
|
||||||
|
import { Attributes } from "../file/xml-components";
|
||||||
import { Utility } from "../tests/utility";
|
import { Utility } from "../tests/utility";
|
||||||
|
|
||||||
describe("Formatter", () => {
|
describe("Formatter", () => {
|
||||||
@ -15,21 +15,21 @@ describe("Formatter", () => {
|
|||||||
|
|
||||||
describe("#format()", () => {
|
describe("#format()", () => {
|
||||||
it("should format simple paragraph", () => {
|
it("should format simple paragraph", () => {
|
||||||
const paragraph = new docx.Paragraph();
|
const paragraph = new file.Paragraph();
|
||||||
const newJson = formatter.format(paragraph);
|
const newJson = formatter.format(paragraph);
|
||||||
assert.isDefined(newJson["w:p"]);
|
assert.isDefined(newJson["w:p"]);
|
||||||
});
|
});
|
||||||
|
|
||||||
it("should remove xmlKeys", () => {
|
it("should remove xmlKeys", () => {
|
||||||
const paragraph = new docx.Paragraph();
|
const paragraph = new file.Paragraph();
|
||||||
const newJson = formatter.format(paragraph);
|
const newJson = formatter.format(paragraph);
|
||||||
const stringifiedJson = JSON.stringify(newJson);
|
const stringifiedJson = JSON.stringify(newJson);
|
||||||
assert(stringifiedJson.indexOf("xmlKeys") < 0);
|
assert(stringifiedJson.indexOf("xmlKeys") < 0);
|
||||||
});
|
});
|
||||||
|
|
||||||
it("should format simple paragraph with bold text", () => {
|
it("should format simple paragraph with bold text", () => {
|
||||||
const paragraph = new docx.Paragraph();
|
const paragraph = new file.Paragraph();
|
||||||
paragraph.addRun(new docx.TextRun("test").bold());
|
paragraph.addRun(new file.TextRun("test").bold());
|
||||||
const newJson = formatter.format(paragraph);
|
const newJson = formatter.format(paragraph);
|
||||||
assert.isDefined(newJson["w:p"][1]["w:r"][0]["w:rPr"][0]["w:b"][0]._attr["w:val"]);
|
assert.isDefined(newJson["w:p"][1]["w:r"][0]["w:rPr"][0]["w:b"][0]._attr["w:val"]);
|
||||||
});
|
});
|
||||||
@ -61,13 +61,13 @@ describe("Formatter", () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
it("should should change 'p' tag into 'w:p' tag", () => {
|
it("should should change 'p' tag into 'w:p' tag", () => {
|
||||||
const paragraph = new docx.Paragraph();
|
const paragraph = new file.Paragraph();
|
||||||
const newJson = formatter.format(paragraph);
|
const newJson = formatter.format(paragraph);
|
||||||
assert.isDefined(newJson["w:p"]);
|
assert.isDefined(newJson["w:p"]);
|
||||||
});
|
});
|
||||||
|
|
||||||
it("should format Properties object correctly", () => {
|
it("should format Properties object correctly", () => {
|
||||||
const properties = new Properties({
|
const properties = new CoreProperties({
|
||||||
title: "test document",
|
title: "test document",
|
||||||
creator: "Dolan",
|
creator: "Dolan",
|
||||||
});
|
});
|
7
src/export/formatter.ts
Normal file
7
src/export/formatter.ts
Normal file
@ -0,0 +1,7 @@
|
|||||||
|
import { BaseXmlComponent, IXmlableObject } from "file/xml-components";
|
||||||
|
|
||||||
|
export class Formatter {
|
||||||
|
public format(input: BaseXmlComponent): IXmlableObject {
|
||||||
|
return input.prepForXml();
|
||||||
|
}
|
||||||
|
}
|
105
src/export/packer/compiler.ts
Normal file
105
src/export/packer/compiler.ts
Normal file
@ -0,0 +1,105 @@
|
|||||||
|
import * as archiver from "archiver";
|
||||||
|
import * as express from "express";
|
||||||
|
import * as fs from "fs";
|
||||||
|
import * as xml from "xml";
|
||||||
|
|
||||||
|
import { File } from "file";
|
||||||
|
import { Formatter } from "../formatter";
|
||||||
|
|
||||||
|
export class Compiler {
|
||||||
|
protected archive: archiver.Archiver;
|
||||||
|
private formatter: Formatter;
|
||||||
|
|
||||||
|
constructor(private file: File) {
|
||||||
|
this.formatter = new Formatter();
|
||||||
|
this.archive = archiver.create("zip", {});
|
||||||
|
|
||||||
|
this.archive.on("error", (err) => {
|
||||||
|
throw err;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
public async compile(output: fs.WriteStream | express.Response): Promise<void> {
|
||||||
|
this.archive.pipe(output);
|
||||||
|
|
||||||
|
const xmlDocument = xml(this.formatter.format(this.file.Document), true);
|
||||||
|
const xmlStyles = xml(this.formatter.format(this.file.Styles));
|
||||||
|
const xmlProperties = xml(this.formatter.format(this.file.CoreProperties), {
|
||||||
|
declaration: {
|
||||||
|
standalone: "yes",
|
||||||
|
encoding: "UTF-8",
|
||||||
|
},
|
||||||
|
});
|
||||||
|
const xmlNumbering = xml(this.formatter.format(this.file.Numbering));
|
||||||
|
const xmlRelationships = xml(this.formatter.format(this.file.DocumentRelationships));
|
||||||
|
const xmlFileRelationships = xml(this.formatter.format(this.file.FileRelationships));
|
||||||
|
const xmlHeader = xml(this.formatter.format(this.file.Header.Header));
|
||||||
|
const xmlFooter = xml(this.formatter.format(this.file.Footer.Footer));
|
||||||
|
const xmlHeaderRelationships = xml(this.formatter.format(this.file.Header.Relationships));
|
||||||
|
const xmlFooterRelationships = xml(this.formatter.format(this.file.Footer.Relationships));
|
||||||
|
const xmlContentTypes = xml(this.formatter.format(this.file.ContentTypes));
|
||||||
|
const xmlAppProperties = xml(this.formatter.format(this.file.AppProperties));
|
||||||
|
|
||||||
|
this.archive.append(xmlDocument, {
|
||||||
|
name: "word/document.xml",
|
||||||
|
});
|
||||||
|
|
||||||
|
this.archive.append(xmlStyles, {
|
||||||
|
name: "word/styles.xml",
|
||||||
|
});
|
||||||
|
|
||||||
|
this.archive.append(xmlProperties, {
|
||||||
|
name: "docProps/core.xml",
|
||||||
|
});
|
||||||
|
|
||||||
|
this.archive.append(xmlAppProperties, {
|
||||||
|
name: "docProps/app.xml",
|
||||||
|
});
|
||||||
|
|
||||||
|
this.archive.append(xmlNumbering, {
|
||||||
|
name: "word/numbering.xml",
|
||||||
|
});
|
||||||
|
|
||||||
|
this.archive.append(xmlHeader, {
|
||||||
|
name: "word/header1.xml",
|
||||||
|
});
|
||||||
|
|
||||||
|
this.archive.append(xmlFooter, {
|
||||||
|
name: "word/footer1.xml",
|
||||||
|
});
|
||||||
|
|
||||||
|
this.archive.append(xmlRelationships, {
|
||||||
|
name: "word/_rels/document.xml.rels",
|
||||||
|
});
|
||||||
|
|
||||||
|
this.archive.append(xmlHeaderRelationships, {
|
||||||
|
name: "word/_rels/header1.xml.rels",
|
||||||
|
});
|
||||||
|
|
||||||
|
this.archive.append(xmlFooterRelationships, {
|
||||||
|
name: "word/_rels/footer1.xml.rels",
|
||||||
|
});
|
||||||
|
|
||||||
|
this.archive.append(xmlContentTypes, {
|
||||||
|
name: "[Content_Types].xml",
|
||||||
|
});
|
||||||
|
|
||||||
|
this.archive.append(xmlFileRelationships, {
|
||||||
|
name: "_rels/.rels",
|
||||||
|
});
|
||||||
|
|
||||||
|
for (const data of this.file.Media.array) {
|
||||||
|
this.archive.append(data.stream, {
|
||||||
|
name: `word/media/${data.fileName}`,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
this.archive.finalize();
|
||||||
|
|
||||||
|
return new Promise<void>((resolve) => {
|
||||||
|
output.on("close", () => {
|
||||||
|
resolve();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
29
src/export/packer/express.ts
Normal file
29
src/export/packer/express.ts
Normal file
@ -0,0 +1,29 @@
|
|||||||
|
import * as express from "express";
|
||||||
|
|
||||||
|
import { File } from "file";
|
||||||
|
import { Compiler } from "./compiler";
|
||||||
|
import { IPacker } from "./packer";
|
||||||
|
|
||||||
|
export class ExpressPacker implements IPacker {
|
||||||
|
private readonly packer: Compiler;
|
||||||
|
|
||||||
|
constructor(file: File, private readonly res: express.Response) {
|
||||||
|
this.packer = new Compiler(file);
|
||||||
|
|
||||||
|
this.res = res;
|
||||||
|
|
||||||
|
this.res.on("close", () => {
|
||||||
|
return res
|
||||||
|
.status(200)
|
||||||
|
.send("OK")
|
||||||
|
.end();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
public async pack(name: string): Promise<void> {
|
||||||
|
name = name.replace(/.docx$/, "");
|
||||||
|
|
||||||
|
this.res.attachment(`${name}.docx`);
|
||||||
|
await this.packer.compile(this.res);
|
||||||
|
}
|
||||||
|
}
|
42
src/export/packer/local.spec.ts
Normal file
42
src/export/packer/local.spec.ts
Normal file
@ -0,0 +1,42 @@
|
|||||||
|
/* tslint:disable:typedef space-before-function-paren */
|
||||||
|
import * as fs from "fs";
|
||||||
|
|
||||||
|
import { LocalPacker } from "../../export/packer/local";
|
||||||
|
import { File, Paragraph } from "../../file";
|
||||||
|
|
||||||
|
describe("LocalPacker", () => {
|
||||||
|
let packer: LocalPacker;
|
||||||
|
|
||||||
|
beforeEach(() => {
|
||||||
|
const file = new File({
|
||||||
|
creator: "Dolan Miu",
|
||||||
|
revision: "1",
|
||||||
|
lastModifiedBy: "Dolan Miu",
|
||||||
|
});
|
||||||
|
const paragraph = new Paragraph("test text");
|
||||||
|
const heading = new Paragraph("Hello world").heading1();
|
||||||
|
file.addParagraph(new Paragraph("title").title());
|
||||||
|
file.addParagraph(heading);
|
||||||
|
file.addParagraph(new Paragraph("heading 2").heading2());
|
||||||
|
file.addParagraph(paragraph);
|
||||||
|
|
||||||
|
packer = new LocalPacker(file);
|
||||||
|
});
|
||||||
|
|
||||||
|
describe("#pack()", () => {
|
||||||
|
it("should create a standard docx file", async function() {
|
||||||
|
this.timeout(99999999);
|
||||||
|
await packer.pack("build/tests/test");
|
||||||
|
fs.statSync("build/tests/test.docx");
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe("#packPdf", () => {
|
||||||
|
it("should create a standard PDF file", async function() {
|
||||||
|
this.timeout(99999999);
|
||||||
|
|
||||||
|
await packer.packPdf("build/tests/pdf-test");
|
||||||
|
fs.statSync("build/tests/pdf-test.pdf");
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
47
src/export/packer/local.ts
Normal file
47
src/export/packer/local.ts
Normal file
@ -0,0 +1,47 @@
|
|||||||
|
import * as fs from "fs";
|
||||||
|
import * as os from "os";
|
||||||
|
import * as path from "path";
|
||||||
|
|
||||||
|
import { File } from "../../file";
|
||||||
|
import { Compiler } from "./compiler";
|
||||||
|
import { IPacker } from "./packer";
|
||||||
|
import { PdfConvertWrapper } from "./pdf-convert-wrapper";
|
||||||
|
|
||||||
|
export class LocalPacker implements IPacker {
|
||||||
|
private stream: fs.WriteStream;
|
||||||
|
private readonly pdfConverter: PdfConvertWrapper;
|
||||||
|
private readonly packer: Compiler;
|
||||||
|
|
||||||
|
constructor(file: File) {
|
||||||
|
this.pdfConverter = new PdfConvertWrapper();
|
||||||
|
this.packer = new Compiler(file);
|
||||||
|
}
|
||||||
|
|
||||||
|
public async pack(filePath: string): Promise<void> {
|
||||||
|
filePath = filePath.replace(/.docx$/, "");
|
||||||
|
|
||||||
|
this.stream = fs.createWriteStream(`${filePath}.docx`);
|
||||||
|
await this.packer.compile(this.stream);
|
||||||
|
}
|
||||||
|
|
||||||
|
public async packPdf(filePath: string): Promise<void> {
|
||||||
|
filePath = filePath.replace(/.pdf$/, "");
|
||||||
|
|
||||||
|
const fileName = path.basename(filePath, path.extname(filePath));
|
||||||
|
const tempPath = path.join(os.tmpdir(), `${fileName}.docx`);
|
||||||
|
this.stream = fs.createWriteStream(tempPath);
|
||||||
|
await this.packer.compile(this.stream);
|
||||||
|
const text = await this.pdfConverter.convert(tempPath);
|
||||||
|
// const writeFile = util.promisify(fs.writeFile); --use this in future, in 3 years time. Only in node 8
|
||||||
|
// return writeFile(`${filePath}.pdf`, text);
|
||||||
|
return new Promise<void>((resolve, reject) => {
|
||||||
|
fs.writeFile(`${filePath}.pdf`, text, (err) => {
|
||||||
|
if (err) {
|
||||||
|
reject(err);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
resolve();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
6
src/export/packer/packer.ts
Normal file
6
src/export/packer/packer.ts
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
export interface IPacker {
|
||||||
|
pack(path: string): void;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Needed because of: https://github.com/s-panferov/awesome-typescript-loader/issues/432
|
||||||
|
export const WORKAROUND = "";
|
35
src/export/packer/pdf-convert-wrapper.ts
Normal file
35
src/export/packer/pdf-convert-wrapper.ts
Normal file
@ -0,0 +1,35 @@
|
|||||||
|
/* tslint:disable:object-literal-key-quotes */
|
||||||
|
// This tslint disable is needed, or it simply won't work
|
||||||
|
import * as fs from "fs";
|
||||||
|
import * as request from "request-promise";
|
||||||
|
|
||||||
|
export interface IConvertOutput {
|
||||||
|
data: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
export class PdfConvertWrapper {
|
||||||
|
public convert(filePath: string): request.RequestPromise {
|
||||||
|
return request.post({
|
||||||
|
url: "http://mirror1.convertonlinefree.com",
|
||||||
|
encoding: null,
|
||||||
|
headers: {
|
||||||
|
"User-Agent":
|
||||||
|
"Mozilla/5.0 (Macintosh; Intel Mac OS X 10_9_4) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/37.0.2062.94 Safari/537.36",
|
||||||
|
},
|
||||||
|
formData: {
|
||||||
|
__EVENTTARGET: "",
|
||||||
|
__EVENTARGUMENT: "",
|
||||||
|
__VIEWSTATE: "",
|
||||||
|
ctl00$MainContent$fu: {
|
||||||
|
value: fs.readFileSync(filePath),
|
||||||
|
options: {
|
||||||
|
filename: "output.docx",
|
||||||
|
contentType: "application/vnd.openxmlformats-officedocument.wordprocessingml.document",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
ctl00$MainContent$btnConvert: "Convert",
|
||||||
|
ctl00$MainContent$fuZip: "",
|
||||||
|
},
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
13
src/file/app-properties/app-properties-attributes.ts
Normal file
13
src/file/app-properties/app-properties-attributes.ts
Normal file
@ -0,0 +1,13 @@
|
|||||||
|
import { XmlAttributeComponent } from "file/xml-components";
|
||||||
|
|
||||||
|
export interface IAppPropertiesAttributes {
|
||||||
|
xmlns: string;
|
||||||
|
vt: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
export class AppPropertiesAttributes extends XmlAttributeComponent<IAppPropertiesAttributes> {
|
||||||
|
protected xmlKeys = {
|
||||||
|
xmlns: "xmlns",
|
||||||
|
vt: "xmlns:vt",
|
||||||
|
};
|
||||||
|
}
|
15
src/file/app-properties/app-properties.ts
Normal file
15
src/file/app-properties/app-properties.ts
Normal file
@ -0,0 +1,15 @@
|
|||||||
|
import { XmlComponent } from "file/xml-components";
|
||||||
|
import { AppPropertiesAttributes } from "./app-properties-attributes";
|
||||||
|
|
||||||
|
export class AppProperties extends XmlComponent {
|
||||||
|
constructor() {
|
||||||
|
super("Properties");
|
||||||
|
|
||||||
|
this.root.push(
|
||||||
|
new AppPropertiesAttributes({
|
||||||
|
xmlns: "http://schemas.openxmlformats.org/officeDocument/2006/extended-properties",
|
||||||
|
vt: "http://schemas.openxmlformats.org/officeDocument/2006/docPropsVTypes",
|
||||||
|
}),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
11
src/file/content-types/content-types-attributes.ts
Normal file
11
src/file/content-types/content-types-attributes.ts
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
import { XmlAttributeComponent } from "file/xml-components";
|
||||||
|
|
||||||
|
export interface IContentTypeAttributes {
|
||||||
|
xmlns?: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
export class ContentTypeAttributes extends XmlAttributeComponent<IContentTypeAttributes> {
|
||||||
|
protected xmlKeys = {
|
||||||
|
xmlns: "xmlns",
|
||||||
|
};
|
||||||
|
}
|
34
src/file/content-types/content-types.ts
Normal file
34
src/file/content-types/content-types.ts
Normal file
@ -0,0 +1,34 @@
|
|||||||
|
import { XmlComponent } from "file/xml-components";
|
||||||
|
import { ContentTypeAttributes } from "./content-types-attributes";
|
||||||
|
import { Default } from "./default/default";
|
||||||
|
import { Override } from "./override/override";
|
||||||
|
|
||||||
|
export class ContentTypes extends XmlComponent {
|
||||||
|
constructor() {
|
||||||
|
super("Types");
|
||||||
|
|
||||||
|
this.root.push(
|
||||||
|
new ContentTypeAttributes({
|
||||||
|
xmlns: "http://schemas.openxmlformats.org/package/2006/content-types",
|
||||||
|
}),
|
||||||
|
);
|
||||||
|
|
||||||
|
this.root.push(new Default("image/png", "png"));
|
||||||
|
this.root.push(new Default("image/jpeg", "jpeg"));
|
||||||
|
this.root.push(new Default("image/jpeg", "jpg"));
|
||||||
|
this.root.push(new Default("image/bmp", "bmp"));
|
||||||
|
this.root.push(new Default("image/gif", "gif"));
|
||||||
|
this.root.push(new Default("application/vnd.openxmlformats-package.relationships+xml", "rels"));
|
||||||
|
this.root.push(new Default("application/xml", "xml"));
|
||||||
|
|
||||||
|
this.root.push(
|
||||||
|
new Override("application/vnd.openxmlformats-officedocument.wordprocessingml.document.main+xml", "/word/document.xml"),
|
||||||
|
);
|
||||||
|
this.root.push(new Override("application/vnd.openxmlformats-officedocument.wordprocessingml.header+xml", "/word/header1.xml"));
|
||||||
|
this.root.push(new Override("application/vnd.openxmlformats-officedocument.wordprocessingml.footer+xml", "/word/footer1.xml"));
|
||||||
|
this.root.push(new Override("application/vnd.openxmlformats-officedocument.wordprocessingml.styles+xml", "/word/styles.xml"));
|
||||||
|
this.root.push(new Override("application/vnd.openxmlformats-package.core-properties+xml", "/docProps/core.xml"));
|
||||||
|
this.root.push(new Override("application/vnd.openxmlformats-officedocument.extended-properties+xml", "/docProps/app.xml"));
|
||||||
|
this.root.push(new Override("application/vnd.openxmlformats-officedocument.wordprocessingml.numbering+xml", "/word/numbering.xml"));
|
||||||
|
}
|
||||||
|
}
|
13
src/file/content-types/default/default-attributes.ts
Normal file
13
src/file/content-types/default/default-attributes.ts
Normal file
@ -0,0 +1,13 @@
|
|||||||
|
import { XmlAttributeComponent } from "file/xml-components";
|
||||||
|
|
||||||
|
export interface IDefaultAttributes {
|
||||||
|
contentType: string;
|
||||||
|
extension?: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
export class DefaultAttributes extends XmlAttributeComponent<IDefaultAttributes> {
|
||||||
|
protected xmlKeys = {
|
||||||
|
contentType: "ContentType",
|
||||||
|
extension: "Extension",
|
||||||
|
};
|
||||||
|
}
|
15
src/file/content-types/default/default.ts
Normal file
15
src/file/content-types/default/default.ts
Normal file
@ -0,0 +1,15 @@
|
|||||||
|
import { XmlComponent } from "file/xml-components";
|
||||||
|
import { DefaultAttributes } from "./default-attributes";
|
||||||
|
|
||||||
|
export class Default extends XmlComponent {
|
||||||
|
constructor(contentType: string, extension?: string) {
|
||||||
|
super("Default");
|
||||||
|
|
||||||
|
this.root.push(
|
||||||
|
new DefaultAttributes({
|
||||||
|
contentType: contentType,
|
||||||
|
extension: extension,
|
||||||
|
}),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
13
src/file/content-types/override/override-attributes.ts
Normal file
13
src/file/content-types/override/override-attributes.ts
Normal file
@ -0,0 +1,13 @@
|
|||||||
|
import { XmlAttributeComponent } from "file/xml-components";
|
||||||
|
|
||||||
|
export interface IOverrideAttributes {
|
||||||
|
contentType: string;
|
||||||
|
partName?: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
export class OverrideAttributes extends XmlAttributeComponent<IOverrideAttributes> {
|
||||||
|
protected xmlKeys = {
|
||||||
|
contentType: "ContentType",
|
||||||
|
partName: "PartName",
|
||||||
|
};
|
||||||
|
}
|
15
src/file/content-types/override/override.ts
Normal file
15
src/file/content-types/override/override.ts
Normal file
@ -0,0 +1,15 @@
|
|||||||
|
import { XmlComponent } from "file/xml-components";
|
||||||
|
import { OverrideAttributes } from "./override-attributes";
|
||||||
|
|
||||||
|
export class Override extends XmlComponent {
|
||||||
|
constructor(contentType: string, partName?: string) {
|
||||||
|
super("Override");
|
||||||
|
|
||||||
|
this.root.push(
|
||||||
|
new OverrideAttributes({
|
||||||
|
contentType: contentType,
|
||||||
|
partName: partName,
|
||||||
|
}),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
@ -1,8 +1,7 @@
|
|||||||
import { DocumentAttributes } from "../docx/document/document-attributes";
|
import { XmlComponent } from "file/xml-components";
|
||||||
import { XmlComponent } from "../docx/xml-components";
|
import { DocumentAttributes } from "../document/document-attributes";
|
||||||
|
|
||||||
export class Title extends XmlComponent {
|
export class Title extends XmlComponent {
|
||||||
|
|
||||||
constructor(value: string) {
|
constructor(value: string) {
|
||||||
super("dc:title");
|
super("dc:title");
|
||||||
this.root.push(value);
|
this.root.push(value);
|
||||||
@ -10,7 +9,6 @@ export class Title extends XmlComponent {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export class Subject extends XmlComponent {
|
export class Subject extends XmlComponent {
|
||||||
|
|
||||||
constructor(value: string) {
|
constructor(value: string) {
|
||||||
super("dc:subject");
|
super("dc:subject");
|
||||||
this.root.push(value);
|
this.root.push(value);
|
||||||
@ -18,7 +16,6 @@ export class Subject extends XmlComponent {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export class Creator extends XmlComponent {
|
export class Creator extends XmlComponent {
|
||||||
|
|
||||||
constructor(value: string) {
|
constructor(value: string) {
|
||||||
super("dc:creator");
|
super("dc:creator");
|
||||||
this.root.push(value);
|
this.root.push(value);
|
||||||
@ -26,7 +23,6 @@ export class Creator extends XmlComponent {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export class Keywords extends XmlComponent {
|
export class Keywords extends XmlComponent {
|
||||||
|
|
||||||
constructor(value: string) {
|
constructor(value: string) {
|
||||||
super("cp:keywords");
|
super("cp:keywords");
|
||||||
this.root.push(value);
|
this.root.push(value);
|
||||||
@ -34,7 +30,6 @@ export class Keywords extends XmlComponent {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export class Description extends XmlComponent {
|
export class Description extends XmlComponent {
|
||||||
|
|
||||||
constructor(value: string) {
|
constructor(value: string) {
|
||||||
super("dc:description");
|
super("dc:description");
|
||||||
this.root.push(value);
|
this.root.push(value);
|
||||||
@ -42,7 +37,6 @@ export class Description extends XmlComponent {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export class LastModifiedBy extends XmlComponent {
|
export class LastModifiedBy extends XmlComponent {
|
||||||
|
|
||||||
constructor(value: string) {
|
constructor(value: string) {
|
||||||
super("cp:lastModifiedBy");
|
super("cp:lastModifiedBy");
|
||||||
this.root.push(value);
|
this.root.push(value);
|
||||||
@ -50,7 +44,6 @@ export class LastModifiedBy extends XmlComponent {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export class Revision extends XmlComponent {
|
export class Revision extends XmlComponent {
|
||||||
|
|
||||||
constructor(value: string) {
|
constructor(value: string) {
|
||||||
super("cp:revision");
|
super("cp:revision");
|
||||||
this.root.push(value);
|
this.root.push(value);
|
||||||
@ -72,23 +65,25 @@ export abstract class DateComponent extends XmlComponent {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export class Created extends DateComponent {
|
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());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export class Modified extends DateComponent {
|
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());
|
||||||
}
|
}
|
||||||
}
|
}
|
1
src/file/core-properties/index.ts
Normal file
1
src/file/core-properties/index.ts
Normal file
@ -0,0 +1 @@
|
|||||||
|
export * from "./properties";
|
@ -1,13 +1,12 @@
|
|||||||
import { expect } from "chai";
|
import { expect } from "chai";
|
||||||
|
|
||||||
import { Formatter } from "../export/formatter";
|
import { Formatter } from "../../export/formatter";
|
||||||
import { Properties } from "./";
|
import { CoreProperties } from "./properties";
|
||||||
|
|
||||||
describe("Properties", () => {
|
describe("Properties", () => {
|
||||||
|
|
||||||
describe("#constructor()", () => {
|
describe("#constructor()", () => {
|
||||||
it("sets the appropriate attributes on the top-level", () => {
|
it("sets the appropriate attributes on the top-level", () => {
|
||||||
const properties = new Properties({});
|
const properties = new CoreProperties({});
|
||||||
const tree = new Formatter().format(properties);
|
const tree = new Formatter().format(properties);
|
||||||
expect(Object.keys(tree)).to.deep.equal(["cp:coreProperties"]);
|
expect(Object.keys(tree)).to.deep.equal(["cp:coreProperties"]);
|
||||||
expect(tree["cp:coreProperties"]).to.be.an.instanceof(Array);
|
expect(tree["cp:coreProperties"]).to.be.an.instanceof(Array);
|
||||||
@ -23,18 +22,16 @@ describe("Properties", () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
it("should create properties with a title", () => {
|
it("should create properties with a title", () => {
|
||||||
const properties = new Properties({title: "test document"});
|
const properties = new CoreProperties({ title: "test document" });
|
||||||
const tree = new Formatter().format(properties);
|
const tree = new Formatter().format(properties);
|
||||||
expect(Object.keys(tree)).to.deep.equal(["cp:coreProperties"]);
|
expect(Object.keys(tree)).to.deep.equal(["cp:coreProperties"]);
|
||||||
expect(tree["cp:coreProperties"]).to.be.an.instanceof(Array);
|
expect(tree["cp:coreProperties"]).to.be.an.instanceof(Array);
|
||||||
expect(Object.keys(tree["cp:coreProperties"][0])).to.deep.equal(["_attr"]);
|
expect(Object.keys(tree["cp:coreProperties"][0])).to.deep.equal(["_attr"]);
|
||||||
expect(tree["cp:coreProperties"][1]).to.deep.equal(
|
expect(tree["cp:coreProperties"][1]).to.deep.equal({ "dc:title": ["test document"] });
|
||||||
{"dc:title": ["test document"]},
|
|
||||||
);
|
|
||||||
});
|
});
|
||||||
|
|
||||||
it("should create properties with all the attributes given", () => {
|
it("should create properties with all the attributes given", () => {
|
||||||
const properties = new Properties({
|
const properties = new CoreProperties({
|
||||||
title: "test document",
|
title: "test document",
|
||||||
subject: "test subject",
|
subject: "test subject",
|
||||||
creator: "me",
|
creator: "me",
|
||||||
@ -60,7 +57,7 @@ describe("Properties", () => {
|
|||||||
"dcterms:created",
|
"dcterms:created",
|
||||||
"dcterms:modified",
|
"dcterms:modified",
|
||||||
]);
|
]);
|
||||||
expect(tree["cp:coreProperties"].slice(1, -2).sort((a, b) => key(a) < key(b) ? -1 : 1)).to.deep.equal([
|
expect(tree["cp:coreProperties"].slice(1, -2).sort((a, b) => (key(a) < key(b) ? -1 : 1))).to.deep.equal([
|
||||||
{ "cp:keywords": ["test docx"] },
|
{ "cp:keywords": ["test docx"] },
|
||||||
{ "cp:lastModifiedBy": ["the author"] },
|
{ "cp:lastModifiedBy": ["the author"] },
|
||||||
{ "cp:revision": ["123"] },
|
{ "cp:revision": ["123"] },
|
@ -1,5 +1,5 @@
|
|||||||
import { DocumentAttributes } from "../docx/document/document-attributes";
|
import { XmlComponent } from "file/xml-components";
|
||||||
import { XmlComponent } from "../docx/xml-components";
|
import { DocumentAttributes } from "../document/document-attributes";
|
||||||
import { Created, Creator, Description, Keywords, LastModifiedBy, Modified, Revision, Subject, Title } from "./components";
|
import { Created, Creator, Description, Keywords, LastModifiedBy, Modified, Revision, Subject, Title } from "./components";
|
||||||
|
|
||||||
export interface IPropertiesOptions {
|
export interface IPropertiesOptions {
|
||||||
@ -12,17 +12,18 @@ export interface IPropertiesOptions {
|
|||||||
revision?: string;
|
revision?: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
export class Properties extends XmlComponent {
|
export class CoreProperties extends XmlComponent {
|
||||||
|
|
||||||
constructor(options: IPropertiesOptions) {
|
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",
|
||||||
}));
|
}),
|
||||||
|
);
|
||||||
if (options.title) {
|
if (options.title) {
|
||||||
this.root.push(new Title(options.title));
|
this.root.push(new Title(options.title));
|
||||||
}
|
}
|
39
src/file/document/body/body.spec.ts
Normal file
39
src/file/document/body/body.spec.ts
Normal file
@ -0,0 +1,39 @@
|
|||||||
|
// import { assert } from "chai";
|
||||||
|
|
||||||
|
// import { Utility } from "../../../tests/utility";
|
||||||
|
// import { Body } from "./";
|
||||||
|
|
||||||
|
describe("Body", () => {
|
||||||
|
// let body: Body;
|
||||||
|
|
||||||
|
beforeEach(() => {
|
||||||
|
// body = new Body();
|
||||||
|
});
|
||||||
|
|
||||||
|
// describe("#constructor()", () => {
|
||||||
|
// it("should create the Section Properties", () => {
|
||||||
|
// const newJson = Utility.jsonify(body);
|
||||||
|
// assert.equal(newJson.root[0].rootKey, "w:sectPr");
|
||||||
|
// });
|
||||||
|
|
||||||
|
// it("should create the Page Size", () => {
|
||||||
|
// const newJson = Utility.jsonify(body);
|
||||||
|
// assert.equal(newJson.root[1].rootKey, "w:pgSz");
|
||||||
|
// });
|
||||||
|
|
||||||
|
// it("should create the Page Margin", () => {
|
||||||
|
// const newJson = Utility.jsonify(body);
|
||||||
|
// assert.equal(newJson.root[2].rootKey, "w:pgMar");
|
||||||
|
// });
|
||||||
|
|
||||||
|
// it("should create the Columns", () => {
|
||||||
|
// const newJson = Utility.jsonify(body);
|
||||||
|
// assert.equal(newJson.root[3].rootKey, "w:cols");
|
||||||
|
// });
|
||||||
|
|
||||||
|
// it("should create the Document Grid", () => {
|
||||||
|
// const newJson = Utility.jsonify(body);
|
||||||
|
// assert.equal(newJson.root[4].rootKey, "w:docGrid");
|
||||||
|
// });
|
||||||
|
// });
|
||||||
|
});
|
14
src/file/document/body/body.ts
Normal file
14
src/file/document/body/body.ts
Normal file
@ -0,0 +1,14 @@
|
|||||||
|
import { XmlComponent } from "file/xml-components";
|
||||||
|
import { SectionProperties, SectionPropertiesOptions } from "./section-properties/section-properties";
|
||||||
|
|
||||||
|
export class Body extends XmlComponent {
|
||||||
|
constructor(sectionPropertiesOptions?: SectionPropertiesOptions) {
|
||||||
|
super("w:body");
|
||||||
|
|
||||||
|
this.root.push(new SectionProperties(sectionPropertiesOptions));
|
||||||
|
}
|
||||||
|
|
||||||
|
public push(component: XmlComponent): void {
|
||||||
|
this.root.push(component);
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,11 @@
|
|||||||
|
import { XmlAttributeComponent } from "file/xml-components";
|
||||||
|
|
||||||
|
export interface IColumnsAttributes {
|
||||||
|
space?: number;
|
||||||
|
}
|
||||||
|
|
||||||
|
export class ColumnsAttributes extends XmlAttributeComponent<IColumnsAttributes> {
|
||||||
|
protected xmlKeys = {
|
||||||
|
space: "w:space",
|
||||||
|
};
|
||||||
|
}
|
13
src/file/document/body/section-properties/columns/columns.ts
Normal file
13
src/file/document/body/section-properties/columns/columns.ts
Normal file
@ -0,0 +1,13 @@
|
|||||||
|
import { XmlComponent } from "file/xml-components";
|
||||||
|
import { ColumnsAttributes } from "./columns-attributes";
|
||||||
|
|
||||||
|
export class Columns extends XmlComponent {
|
||||||
|
constructor(space: number) {
|
||||||
|
super("w:cols");
|
||||||
|
this.root.push(
|
||||||
|
new ColumnsAttributes({
|
||||||
|
space: space,
|
||||||
|
}),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,11 @@
|
|||||||
|
import { XmlAttributeComponent } from "file/xml-components";
|
||||||
|
|
||||||
|
export interface IDocGridAttributesProperties {
|
||||||
|
linePitch?: number;
|
||||||
|
}
|
||||||
|
|
||||||
|
export class DocGridAttributes extends XmlAttributeComponent<IDocGridAttributesProperties> {
|
||||||
|
protected xmlKeys = {
|
||||||
|
linePitch: "w:linePitch",
|
||||||
|
};
|
||||||
|
}
|
@ -0,0 +1,13 @@
|
|||||||
|
import { XmlComponent } from "file/xml-components";
|
||||||
|
import { DocGridAttributes } from "./doc-grid-attributes";
|
||||||
|
|
||||||
|
export class DocumentGrid extends XmlComponent {
|
||||||
|
constructor(linePitch: number) {
|
||||||
|
super("w:docGrid");
|
||||||
|
this.root.push(
|
||||||
|
new DocGridAttributes({
|
||||||
|
linePitch: linePitch,
|
||||||
|
}),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,13 @@
|
|||||||
|
import { XmlAttributeComponent } from "file/xml-components";
|
||||||
|
|
||||||
|
export interface IFooterReferenceAttributes {
|
||||||
|
type: string;
|
||||||
|
id: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
export class FooterReferenceAttributes extends XmlAttributeComponent<IFooterReferenceAttributes> {
|
||||||
|
protected xmlKeys = {
|
||||||
|
type: "w:type",
|
||||||
|
id: "r:id",
|
||||||
|
};
|
||||||
|
}
|
@ -0,0 +1,14 @@
|
|||||||
|
import { XmlComponent } from "file/xml-components";
|
||||||
|
import { FooterReferenceAttributes } from "./footer-reference-attributes";
|
||||||
|
|
||||||
|
export class FooterReference extends XmlComponent {
|
||||||
|
constructor() {
|
||||||
|
super("w:footerReference");
|
||||||
|
this.root.push(
|
||||||
|
new FooterReferenceAttributes({
|
||||||
|
type: "default",
|
||||||
|
id: `rId${4}`,
|
||||||
|
}),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,13 @@
|
|||||||
|
import { XmlAttributeComponent } from "file/xml-components";
|
||||||
|
|
||||||
|
export interface IHeaderReferenceAttributes {
|
||||||
|
type: string;
|
||||||
|
id: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
export class HeaderReferenceAttributes extends XmlAttributeComponent<IHeaderReferenceAttributes> {
|
||||||
|
protected xmlKeys = {
|
||||||
|
type: "w:type",
|
||||||
|
id: "r:id",
|
||||||
|
};
|
||||||
|
}
|
@ -0,0 +1,14 @@
|
|||||||
|
import { XmlComponent } from "file/xml-components";
|
||||||
|
import { HeaderReferenceAttributes } from "./header-reference-attributes";
|
||||||
|
|
||||||
|
export class HeaderReference extends XmlComponent {
|
||||||
|
constructor() {
|
||||||
|
super("w:headerReference");
|
||||||
|
this.root.push(
|
||||||
|
new HeaderReferenceAttributes({
|
||||||
|
type: "default",
|
||||||
|
id: `rId${3}`,
|
||||||
|
}),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,23 @@
|
|||||||
|
import { XmlAttributeComponent } from "file/xml-components";
|
||||||
|
|
||||||
|
export interface IPageMarginAttributes {
|
||||||
|
top?: number;
|
||||||
|
right?: number;
|
||||||
|
bottom?: number;
|
||||||
|
left?: number;
|
||||||
|
header?: number;
|
||||||
|
footer?: number;
|
||||||
|
gutter?: number;
|
||||||
|
}
|
||||||
|
|
||||||
|
export class PageMarginAttributes extends XmlAttributeComponent<IPageMarginAttributes> {
|
||||||
|
protected xmlKeys = {
|
||||||
|
top: "w:top",
|
||||||
|
right: "w:right",
|
||||||
|
bottom: "w:bottom",
|
||||||
|
left: "w:left",
|
||||||
|
header: "w:header",
|
||||||
|
footer: "w:footer",
|
||||||
|
gutter: "w:gutter",
|
||||||
|
};
|
||||||
|
}
|
@ -0,0 +1,19 @@
|
|||||||
|
import { XmlComponent } from "file/xml-components";
|
||||||
|
import { PageMarginAttributes } from "./page-margin-attributes";
|
||||||
|
|
||||||
|
export class PageMargin extends XmlComponent {
|
||||||
|
constructor(top: number, right: number, bottom: number, left: number, header: number, footer: number, gutter: number) {
|
||||||
|
super("w:pgMar");
|
||||||
|
this.root.push(
|
||||||
|
new PageMarginAttributes({
|
||||||
|
top: top,
|
||||||
|
right: right,
|
||||||
|
bottom: bottom,
|
||||||
|
left: left,
|
||||||
|
header: header,
|
||||||
|
footer: footer,
|
||||||
|
gutter: gutter,
|
||||||
|
}),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,15 @@
|
|||||||
|
import { XmlAttributeComponent } from "file/xml-components";
|
||||||
|
|
||||||
|
export interface IPageSizeAttributes {
|
||||||
|
width?: number;
|
||||||
|
height?: number;
|
||||||
|
orientation?: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
export class PageSizeAttributes extends XmlAttributeComponent<IPageSizeAttributes> {
|
||||||
|
protected xmlKeys = {
|
||||||
|
width: "w:w",
|
||||||
|
height: "w:h",
|
||||||
|
orientation: "w:orient",
|
||||||
|
};
|
||||||
|
}
|
@ -0,0 +1,26 @@
|
|||||||
|
import { expect } from "chai";
|
||||||
|
|
||||||
|
import { Formatter } from "../../../../../export/formatter";
|
||||||
|
import { PageSize } from "./page-size";
|
||||||
|
|
||||||
|
describe("PageSize", () => {
|
||||||
|
describe("#constructor()", () => {
|
||||||
|
it("should create page size with portrait", () => {
|
||||||
|
const properties = new PageSize(100, 200, "portrait");
|
||||||
|
const tree = new Formatter().format(properties);
|
||||||
|
|
||||||
|
expect(Object.keys(tree)).to.deep.equal(["w:pgSz"]);
|
||||||
|
expect(tree["w:pgSz"]).to.be.an.instanceof(Array);
|
||||||
|
expect(tree["w:pgSz"][0]).to.deep.equal({ _attr: { "w:h": 200, "w:w": 100, "w:orient": "portrait" } });
|
||||||
|
});
|
||||||
|
|
||||||
|
it("should create page size with horizontal and invert the lengths", () => {
|
||||||
|
const properties = new PageSize(100, 200, "landscape");
|
||||||
|
const tree = new Formatter().format(properties);
|
||||||
|
|
||||||
|
expect(Object.keys(tree)).to.deep.equal(["w:pgSz"]);
|
||||||
|
expect(tree["w:pgSz"]).to.be.an.instanceof(Array);
|
||||||
|
expect(tree["w:pgSz"][0]).to.deep.equal({ _attr: { "w:h": 100, "w:w": 200, "w:orient": "landscape" } });
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
@ -0,0 +1,18 @@
|
|||||||
|
import { XmlComponent } from "file/xml-components";
|
||||||
|
import { PageSizeAttributes } from "./page-size-attributes";
|
||||||
|
|
||||||
|
export class PageSize extends XmlComponent {
|
||||||
|
constructor(width: number, height: number, orientation: string) {
|
||||||
|
super("w:pgSz");
|
||||||
|
|
||||||
|
const flip = orientation === "landscape";
|
||||||
|
|
||||||
|
this.root.push(
|
||||||
|
new PageSizeAttributes({
|
||||||
|
width: flip ? height : width,
|
||||||
|
height: flip ? width : height,
|
||||||
|
orientation: orientation,
|
||||||
|
}),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,142 @@
|
|||||||
|
import { expect } from "chai";
|
||||||
|
|
||||||
|
import { Formatter } from "../../../../export/formatter";
|
||||||
|
import { SectionProperties } from "./section-properties";
|
||||||
|
|
||||||
|
describe("SectionProperties", () => {
|
||||||
|
describe("#constructor()", () => {
|
||||||
|
it("should create section properties with options", () => {
|
||||||
|
const properties = new SectionProperties({
|
||||||
|
width: 11906,
|
||||||
|
height: 16838,
|
||||||
|
top: 1440,
|
||||||
|
right: 1440,
|
||||||
|
bottom: 1440,
|
||||||
|
left: 1440,
|
||||||
|
header: 708,
|
||||||
|
footer: 708,
|
||||||
|
gutter: 0,
|
||||||
|
space: 708,
|
||||||
|
linePitch: 360,
|
||||||
|
});
|
||||||
|
const tree = new Formatter().format(properties);
|
||||||
|
expect(Object.keys(tree)).to.deep.equal(["w:sectPr"]);
|
||||||
|
expect(tree["w:sectPr"]).to.be.an.instanceof(Array);
|
||||||
|
expect(tree["w:sectPr"][0]).to.deep.equal({ "w:pgSz": [{ _attr: { "w:h": 16838, "w:w": 11906, "w:orient": "portrait" } }] });
|
||||||
|
expect(tree["w:sectPr"][1]).to.deep.equal({
|
||||||
|
"w:pgMar": [
|
||||||
|
{
|
||||||
|
_attr: {
|
||||||
|
"w:bottom": 1440,
|
||||||
|
"w:footer": 708,
|
||||||
|
"w:top": 1440,
|
||||||
|
"w:right": 1440,
|
||||||
|
"w:left": 1440,
|
||||||
|
"w:header": 708,
|
||||||
|
"w:gutter": 0,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
],
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
it("should create section properties with no options", () => {
|
||||||
|
const properties = new SectionProperties();
|
||||||
|
const tree = new Formatter().format(properties);
|
||||||
|
expect(Object.keys(tree)).to.deep.equal(["w:sectPr"]);
|
||||||
|
expect(tree["w:sectPr"]).to.be.an.instanceof(Array);
|
||||||
|
expect(tree["w:sectPr"][0]).to.deep.equal({ "w:pgSz": [{ _attr: { "w:h": 16838, "w:w": 11906, "w:orient": "portrait" } }] });
|
||||||
|
expect(tree["w:sectPr"][1]).to.deep.equal({
|
||||||
|
"w:pgMar": [
|
||||||
|
{
|
||||||
|
_attr: {
|
||||||
|
"w:bottom": 1440,
|
||||||
|
"w:footer": 708,
|
||||||
|
"w:top": 1440,
|
||||||
|
"w:right": 1440,
|
||||||
|
"w:left": 1440,
|
||||||
|
"w:header": 708,
|
||||||
|
"w:gutter": 0,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
],
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
it("should create section properties with changed options", () => {
|
||||||
|
const properties = new SectionProperties({
|
||||||
|
top: 0,
|
||||||
|
});
|
||||||
|
const tree = new Formatter().format(properties);
|
||||||
|
expect(Object.keys(tree)).to.deep.equal(["w:sectPr"]);
|
||||||
|
expect(tree["w:sectPr"]).to.be.an.instanceof(Array);
|
||||||
|
expect(tree["w:sectPr"][0]).to.deep.equal({ "w:pgSz": [{ _attr: { "w:h": 16838, "w:w": 11906, "w:orient": "portrait" } }] });
|
||||||
|
expect(tree["w:sectPr"][1]).to.deep.equal({
|
||||||
|
"w:pgMar": [
|
||||||
|
{
|
||||||
|
_attr: {
|
||||||
|
"w:bottom": 1440,
|
||||||
|
"w:footer": 708,
|
||||||
|
"w:top": 0,
|
||||||
|
"w:right": 1440,
|
||||||
|
"w:left": 1440,
|
||||||
|
"w:header": 708,
|
||||||
|
"w:gutter": 0,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
],
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
it("should create section properties with changed options", () => {
|
||||||
|
const properties = new SectionProperties({
|
||||||
|
bottom: 0,
|
||||||
|
});
|
||||||
|
const tree = new Formatter().format(properties);
|
||||||
|
expect(Object.keys(tree)).to.deep.equal(["w:sectPr"]);
|
||||||
|
expect(tree["w:sectPr"]).to.be.an.instanceof(Array);
|
||||||
|
expect(tree["w:sectPr"][0]).to.deep.equal({ "w:pgSz": [{ _attr: { "w:h": 16838, "w:w": 11906, "w:orient": "portrait" } }] });
|
||||||
|
expect(tree["w:sectPr"][1]).to.deep.equal({
|
||||||
|
"w:pgMar": [
|
||||||
|
{
|
||||||
|
_attr: {
|
||||||
|
"w:bottom": 0,
|
||||||
|
"w:footer": 708,
|
||||||
|
"w:top": 1440,
|
||||||
|
"w:right": 1440,
|
||||||
|
"w:left": 1440,
|
||||||
|
"w:header": 708,
|
||||||
|
"w:gutter": 0,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
],
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
it("should create section properties with changed options", () => {
|
||||||
|
const properties = new SectionProperties({
|
||||||
|
width: 0,
|
||||||
|
height: 0,
|
||||||
|
});
|
||||||
|
const tree = new Formatter().format(properties);
|
||||||
|
expect(Object.keys(tree)).to.deep.equal(["w:sectPr"]);
|
||||||
|
expect(tree["w:sectPr"]).to.be.an.instanceof(Array);
|
||||||
|
expect(tree["w:sectPr"][0]).to.deep.equal({ "w:pgSz": [{ _attr: { "w:h": 0, "w:w": 0, "w:orient": "portrait" } }] });
|
||||||
|
expect(tree["w:sectPr"][1]).to.deep.equal({
|
||||||
|
"w:pgMar": [
|
||||||
|
{
|
||||||
|
_attr: {
|
||||||
|
"w:bottom": 1440,
|
||||||
|
"w:footer": 708,
|
||||||
|
"w:top": 1440,
|
||||||
|
"w:right": 1440,
|
||||||
|
"w:left": 1440,
|
||||||
|
"w:header": 708,
|
||||||
|
"w:gutter": 0,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
],
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
@ -0,0 +1,57 @@
|
|||||||
|
// http://officeopenxml.com/WPsection.php
|
||||||
|
import { XmlComponent } from "file/xml-components";
|
||||||
|
import { Columns } from "./columns/columns";
|
||||||
|
import { IColumnsAttributes } from "./columns/columns-attributes";
|
||||||
|
import { DocumentGrid } from "./doc-grid/doc-grid";
|
||||||
|
import { IDocGridAttributesProperties } from "./doc-grid/doc-grid-attributes";
|
||||||
|
import { FooterReference } from "./footer-reference/footer-reference";
|
||||||
|
import { HeaderReference } from "./header-reference/header-reference";
|
||||||
|
import { PageMargin } from "./page-margin/page-margin";
|
||||||
|
import { IPageMarginAttributes } from "./page-margin/page-margin-attributes";
|
||||||
|
import { PageSize } from "./page-size/page-size";
|
||||||
|
import { IPageSizeAttributes } from "./page-size/page-size-attributes";
|
||||||
|
|
||||||
|
export type SectionPropertiesOptions = IPageSizeAttributes & IPageMarginAttributes & IColumnsAttributes & IDocGridAttributesProperties;
|
||||||
|
|
||||||
|
export class SectionProperties extends XmlComponent {
|
||||||
|
constructor(options?: SectionPropertiesOptions) {
|
||||||
|
super("w:sectPr");
|
||||||
|
|
||||||
|
const defaultOptions = {
|
||||||
|
width: 11906,
|
||||||
|
height: 16838,
|
||||||
|
top: 1440,
|
||||||
|
right: 1440,
|
||||||
|
bottom: 1440,
|
||||||
|
left: 1440,
|
||||||
|
header: 708,
|
||||||
|
footer: 708,
|
||||||
|
gutter: 0,
|
||||||
|
space: 708,
|
||||||
|
linePitch: 360,
|
||||||
|
orientation: "portrait",
|
||||||
|
};
|
||||||
|
|
||||||
|
const mergedOptions = {
|
||||||
|
...defaultOptions,
|
||||||
|
...options,
|
||||||
|
};
|
||||||
|
|
||||||
|
this.root.push(new PageSize(mergedOptions.width, mergedOptions.height, mergedOptions.orientation));
|
||||||
|
this.root.push(
|
||||||
|
new PageMargin(
|
||||||
|
mergedOptions.top,
|
||||||
|
mergedOptions.right,
|
||||||
|
mergedOptions.bottom,
|
||||||
|
mergedOptions.left,
|
||||||
|
mergedOptions.header,
|
||||||
|
mergedOptions.footer,
|
||||||
|
mergedOptions.gutter,
|
||||||
|
),
|
||||||
|
);
|
||||||
|
this.root.push(new Columns(mergedOptions.space));
|
||||||
|
this.root.push(new DocumentGrid(mergedOptions.linePitch));
|
||||||
|
this.root.push(new HeaderReference());
|
||||||
|
this.root.push(new FooterReference());
|
||||||
|
}
|
||||||
|
}
|
@ -1,4 +1,4 @@
|
|||||||
import { XmlAttributeComponent } from "../xml-components";
|
import { XmlAttributeComponent } from "file/xml-components";
|
||||||
|
|
||||||
export interface IDocumentAttributesProperties {
|
export interface IDocumentAttributesProperties {
|
||||||
wpc?: string;
|
wpc?: string;
|
83
src/file/document/document.spec.ts
Normal file
83
src/file/document/document.spec.ts
Normal file
@ -0,0 +1,83 @@
|
|||||||
|
import { assert, expect } from "chai";
|
||||||
|
|
||||||
|
import { Formatter } from "../../export/formatter";
|
||||||
|
import { Paragraph } from "../paragraph";
|
||||||
|
import { Table } from "../table";
|
||||||
|
import { Document } from "./document";
|
||||||
|
|
||||||
|
describe("Document", () => {
|
||||||
|
let document: Document;
|
||||||
|
|
||||||
|
beforeEach(() => {
|
||||||
|
document = new Document();
|
||||||
|
});
|
||||||
|
|
||||||
|
describe("#constructor()", () => {
|
||||||
|
it("should create valid JSON", () => {
|
||||||
|
const stringifiedJson = JSON.stringify(document);
|
||||||
|
|
||||||
|
try {
|
||||||
|
JSON.parse(stringifiedJson);
|
||||||
|
} catch (e) {
|
||||||
|
assert.isTrue(false);
|
||||||
|
}
|
||||||
|
assert.isTrue(true);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe("#createParagraph", () => {
|
||||||
|
it("should create a new paragraph and append it to body", () => {
|
||||||
|
const para = document.createParagraph();
|
||||||
|
expect(para).to.be.an.instanceof(Paragraph);
|
||||||
|
const body = new Formatter().format(document)["w:document"][1]["w:body"];
|
||||||
|
expect(body)
|
||||||
|
.to.be.an("array")
|
||||||
|
.which.has.length.at.least(1);
|
||||||
|
expect(body[1]).to.have.property("w:p");
|
||||||
|
});
|
||||||
|
|
||||||
|
it("should use the text given to create a run in the paragraph", () => {
|
||||||
|
const para = document.createParagraph("sample paragraph text");
|
||||||
|
expect(para).to.be.an.instanceof(Paragraph);
|
||||||
|
const body = new Formatter().format(document)["w:document"][1]["w:body"];
|
||||||
|
expect(body)
|
||||||
|
.to.be.an("array")
|
||||||
|
.which.has.length.at.least(1);
|
||||||
|
expect(body[1])
|
||||||
|
.to.have.property("w:p")
|
||||||
|
.which.includes({
|
||||||
|
"w:r": [{ "w:rPr": [] }, { "w:t": [{ _attr: { "xml:space": "preserve" } }, "sample paragraph text"] }],
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe("#createTable", () => {
|
||||||
|
it("should create a new table and append it to body", () => {
|
||||||
|
const table = document.createTable(2, 3);
|
||||||
|
expect(table).to.be.an.instanceof(Table);
|
||||||
|
const body = new Formatter().format(document)["w:document"][1]["w:body"];
|
||||||
|
expect(body)
|
||||||
|
.to.be.an("array")
|
||||||
|
.which.has.length.at.least(1);
|
||||||
|
expect(body[1]).to.have.property("w:tbl");
|
||||||
|
});
|
||||||
|
|
||||||
|
it("should create a table with the correct dimensions", () => {
|
||||||
|
document.createTable(2, 3);
|
||||||
|
const body = new Formatter().format(document)["w:document"][1]["w:body"];
|
||||||
|
expect(body)
|
||||||
|
.to.be.an("array")
|
||||||
|
.which.has.length.at.least(1);
|
||||||
|
expect(body[1])
|
||||||
|
.to.have.property("w:tbl")
|
||||||
|
.which.includes({
|
||||||
|
"w:tblGrid": [
|
||||||
|
{ "w:gridCol": [{ _attr: { "w:w": 1 } }] },
|
||||||
|
{ "w:gridCol": [{ _attr: { "w:w": 1 } }] },
|
||||||
|
{ "w:gridCol": [{ _attr: { "w:w": 1 } }] },
|
||||||
|
],
|
||||||
|
});
|
||||||
|
expect(body[1]["w:tbl"].filter((x) => x["w:tr"])).to.have.length(2);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
73
src/file/document/document.ts
Normal file
73
src/file/document/document.ts
Normal file
@ -0,0 +1,73 @@
|
|||||||
|
// http://officeopenxml.com/WPdocument.php
|
||||||
|
import { IMediaData } from "file/media";
|
||||||
|
import { XmlComponent } from "file/xml-components";
|
||||||
|
import { Paragraph, PictureRun } from "../paragraph";
|
||||||
|
import { Table } from "../table";
|
||||||
|
import { Body } from "./body";
|
||||||
|
import { SectionPropertiesOptions } from "./body/section-properties/section-properties";
|
||||||
|
import { DocumentAttributes } from "./document-attributes";
|
||||||
|
|
||||||
|
export class Document extends XmlComponent {
|
||||||
|
private readonly body: Body;
|
||||||
|
|
||||||
|
constructor(sectionPropertiesOptions?: SectionPropertiesOptions) {
|
||||||
|
super("w:document");
|
||||||
|
this.root.push(
|
||||||
|
new DocumentAttributes({
|
||||||
|
wpc: "http://schemas.microsoft.com/office/word/2010/wordprocessingCanvas",
|
||||||
|
mc: "http://schemas.openxmlformats.org/markup-compatibility/2006",
|
||||||
|
o: "urn:schemas-microsoft-com:office:office",
|
||||||
|
r: "http://schemas.openxmlformats.org/officeDocument/2006/relationships",
|
||||||
|
m: "http://schemas.openxmlformats.org/officeDocument/2006/math",
|
||||||
|
v: "urn:schemas-microsoft-com:vml",
|
||||||
|
wp14: "http://schemas.microsoft.com/office/word/2010/wordprocessingDrawing",
|
||||||
|
wp: "http://schemas.openxmlformats.org/drawingml/2006/wordprocessingDrawing",
|
||||||
|
w10: "urn:schemas-microsoft-com:office:word",
|
||||||
|
w: "http://schemas.openxmlformats.org/wordprocessingml/2006/main",
|
||||||
|
w14: "http://schemas.microsoft.com/office/word/2010/wordml",
|
||||||
|
w15: "http://schemas.microsoft.com/office/word/2012/wordml",
|
||||||
|
wpg: "http://schemas.microsoft.com/office/word/2010/wordprocessingGroup",
|
||||||
|
wpi: "http://schemas.microsoft.com/office/word/2010/wordprocessingInk",
|
||||||
|
wne: "http://schemas.microsoft.com/office/word/2006/wordml",
|
||||||
|
wps: "http://schemas.microsoft.com/office/word/2010/wordprocessingShape",
|
||||||
|
Ignorable: "w14 w15 wp14",
|
||||||
|
}),
|
||||||
|
);
|
||||||
|
this.body = new Body(sectionPropertiesOptions);
|
||||||
|
this.root.push(this.body);
|
||||||
|
}
|
||||||
|
|
||||||
|
public addParagraph(paragraph: Paragraph): void {
|
||||||
|
this.body.push(paragraph);
|
||||||
|
}
|
||||||
|
|
||||||
|
public createParagraph(text?: string): Paragraph {
|
||||||
|
const para = new Paragraph(text);
|
||||||
|
this.addParagraph(para);
|
||||||
|
return para;
|
||||||
|
}
|
||||||
|
|
||||||
|
public addTable(table: Table): void {
|
||||||
|
this.body.push(table);
|
||||||
|
}
|
||||||
|
|
||||||
|
public createTable(rows: number, cols: number): Table {
|
||||||
|
const table = new Table(rows, cols);
|
||||||
|
this.addTable(table);
|
||||||
|
return table;
|
||||||
|
}
|
||||||
|
|
||||||
|
public addDrawing(imageData: IMediaData): void {
|
||||||
|
const paragraph = new Paragraph();
|
||||||
|
const run = new PictureRun(imageData);
|
||||||
|
paragraph.addRun(run);
|
||||||
|
|
||||||
|
this.body.push(paragraph);
|
||||||
|
}
|
||||||
|
|
||||||
|
public createDrawing(imageData: IMediaData): void {
|
||||||
|
this.addDrawing(imageData);
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
@ -1,19 +1,29 @@
|
|||||||
import { assert } from "chai";
|
import { assert } from "chai";
|
||||||
import * as fs from "fs";
|
import * as fs from "fs";
|
||||||
|
|
||||||
import { Utility } from "../../../../tests/utility";
|
import { Utility } from "../../tests/utility";
|
||||||
import { Drawing } from "./";
|
import { Drawing } from "./";
|
||||||
|
|
||||||
describe("Drawing", () => {
|
describe("Drawing", () => {
|
||||||
let currentBreak: Drawing;
|
let currentBreak: Drawing;
|
||||||
|
|
||||||
beforeEach(() => {
|
beforeEach(() => {
|
||||||
const path = "./demo/penguins.jpg";
|
const path = "./demo/images/image1.jpeg";
|
||||||
currentBreak = new Drawing({
|
currentBreak = new Drawing({
|
||||||
fileName: "test.jpg",
|
fileName: "test.jpg",
|
||||||
referenceId: 1,
|
referenceId: 1,
|
||||||
stream: fs.createReadStream(path),
|
stream: fs.createReadStream(path),
|
||||||
path: path,
|
path: path,
|
||||||
|
dimensions: {
|
||||||
|
pixels: {
|
||||||
|
x: 100,
|
||||||
|
y: 100,
|
||||||
|
},
|
||||||
|
emus: {
|
||||||
|
x: 100 * 9525,
|
||||||
|
y: 100 * 9525,
|
||||||
|
},
|
||||||
|
},
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
@ -1,16 +1,15 @@
|
|||||||
import { IData } from "../../../../media/data";
|
import { IMediaData } from "file/media";
|
||||||
import { XmlComponent } from "../../../xml-components";
|
import { XmlComponent } from "file/xml-components";
|
||||||
import { Inline } from "./inline";
|
import { Inline } from "./inline";
|
||||||
|
|
||||||
export class Drawing extends XmlComponent {
|
export class Drawing extends XmlComponent {
|
||||||
|
constructor(imageData: IMediaData) {
|
||||||
constructor(imageData: IData) {
|
|
||||||
super("w:drawing");
|
super("w:drawing");
|
||||||
|
|
||||||
if (imageData === undefined) {
|
if (imageData === undefined) {
|
||||||
throw new Error("imageData cannot be undefined");
|
throw new Error("imageData cannot be undefined");
|
||||||
}
|
}
|
||||||
|
|
||||||
this.root.push(new Inline(imageData.referenceId));
|
this.root.push(new Inline(imageData.referenceId, imageData.dimensions));
|
||||||
}
|
}
|
||||||
}
|
}
|
1
src/file/drawing/index.ts
Normal file
1
src/file/drawing/index.ts
Normal file
@ -0,0 +1 @@
|
|||||||
|
export { Drawing } from "./drawing";
|
@ -0,0 +1,15 @@
|
|||||||
|
import { XmlAttributeComponent } from "file/xml-components";
|
||||||
|
|
||||||
|
export interface IDocPropertiesAttributes {
|
||||||
|
id?: number;
|
||||||
|
name?: string;
|
||||||
|
descr?: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
export class DocPropertiesAttributes extends XmlAttributeComponent<IDocPropertiesAttributes> {
|
||||||
|
protected xmlKeys = {
|
||||||
|
id: "id",
|
||||||
|
name: "name",
|
||||||
|
descr: "descr",
|
||||||
|
};
|
||||||
|
}
|
16
src/file/drawing/inline/doc-properties/doc-properties.ts
Normal file
16
src/file/drawing/inline/doc-properties/doc-properties.ts
Normal file
@ -0,0 +1,16 @@
|
|||||||
|
import { XmlComponent } from "file/xml-components";
|
||||||
|
import { DocPropertiesAttributes } from "./doc-properties-attributes";
|
||||||
|
|
||||||
|
export class DocProperties extends XmlComponent {
|
||||||
|
constructor() {
|
||||||
|
super("wp:docPr");
|
||||||
|
|
||||||
|
this.root.push(
|
||||||
|
new DocPropertiesAttributes({
|
||||||
|
id: 0,
|
||||||
|
name: "",
|
||||||
|
descr: "",
|
||||||
|
}),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,17 @@
|
|||||||
|
import { XmlAttributeComponent } from "file/xml-components";
|
||||||
|
|
||||||
|
export interface IEffectExtentAttributes {
|
||||||
|
b?: number;
|
||||||
|
l?: number;
|
||||||
|
r?: number;
|
||||||
|
t?: number;
|
||||||
|
}
|
||||||
|
|
||||||
|
export class EffectExtentAttributes extends XmlAttributeComponent<IEffectExtentAttributes> {
|
||||||
|
protected xmlKeys = {
|
||||||
|
b: "b",
|
||||||
|
l: "l",
|
||||||
|
r: "r",
|
||||||
|
t: "t",
|
||||||
|
};
|
||||||
|
}
|
17
src/file/drawing/inline/effect-extent/effect-extent.ts
Normal file
17
src/file/drawing/inline/effect-extent/effect-extent.ts
Normal file
@ -0,0 +1,17 @@
|
|||||||
|
import { XmlComponent } from "file/xml-components";
|
||||||
|
import { EffectExtentAttributes } from "./effect-extent-attributes";
|
||||||
|
|
||||||
|
export class EffectExtent extends XmlComponent {
|
||||||
|
constructor() {
|
||||||
|
super("wp:effectExtent");
|
||||||
|
|
||||||
|
this.root.push(
|
||||||
|
new EffectExtentAttributes({
|
||||||
|
b: 0,
|
||||||
|
l: 0,
|
||||||
|
r: 0,
|
||||||
|
t: 0,
|
||||||
|
}),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
13
src/file/drawing/inline/extent/extent-attributes.ts
Normal file
13
src/file/drawing/inline/extent/extent-attributes.ts
Normal file
@ -0,0 +1,13 @@
|
|||||||
|
import { XmlAttributeComponent } from "file/xml-components";
|
||||||
|
|
||||||
|
export interface IExtentAttributes {
|
||||||
|
cx?: number;
|
||||||
|
cy?: number;
|
||||||
|
}
|
||||||
|
|
||||||
|
export class ExtentAttributes extends XmlAttributeComponent<IExtentAttributes> {
|
||||||
|
protected xmlKeys = {
|
||||||
|
cx: "cx",
|
||||||
|
cy: "cy",
|
||||||
|
};
|
||||||
|
}
|
15
src/file/drawing/inline/extent/extent.ts
Normal file
15
src/file/drawing/inline/extent/extent.ts
Normal file
@ -0,0 +1,15 @@
|
|||||||
|
import { XmlComponent } from "file/xml-components";
|
||||||
|
import { ExtentAttributes } from "./extent-attributes";
|
||||||
|
|
||||||
|
export class Extent extends XmlComponent {
|
||||||
|
constructor(x: number, y: number) {
|
||||||
|
super("wp:extent");
|
||||||
|
|
||||||
|
this.root.push(
|
||||||
|
new ExtentAttributes({
|
||||||
|
cx: x,
|
||||||
|
cy: y,
|
||||||
|
}),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,13 @@
|
|||||||
|
import { XmlAttributeComponent } from "file/xml-components";
|
||||||
|
|
||||||
|
export interface IGraphicFrameLockAttributes {
|
||||||
|
xmlns?: string;
|
||||||
|
noChangeAspect?: number;
|
||||||
|
}
|
||||||
|
|
||||||
|
export class GraphicFrameLockAttributes extends XmlAttributeComponent<IGraphicFrameLockAttributes> {
|
||||||
|
protected xmlKeys = {
|
||||||
|
xmlns: "xmlns:a",
|
||||||
|
noChangeAspect: "noChangeAspect",
|
||||||
|
};
|
||||||
|
}
|
@ -0,0 +1,15 @@
|
|||||||
|
import { XmlComponent } from "file/xml-components";
|
||||||
|
import { GraphicFrameLockAttributes } from "./graphic-frame-lock-attributes";
|
||||||
|
|
||||||
|
export class GraphicFrameLocks extends XmlComponent {
|
||||||
|
constructor() {
|
||||||
|
super("a:graphicFrameLocks");
|
||||||
|
|
||||||
|
this.root.push(
|
||||||
|
new GraphicFrameLockAttributes({
|
||||||
|
xmlns: "http://schemas.openxmlformats.org/drawingml/2006/main",
|
||||||
|
noChangeAspect: 1,
|
||||||
|
}),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,10 @@
|
|||||||
|
import { XmlComponent } from "file/xml-components";
|
||||||
|
import { GraphicFrameLocks } from "./graphic-frame-locks/graphic-frame-locks";
|
||||||
|
|
||||||
|
export class GraphicFrameProperties extends XmlComponent {
|
||||||
|
constructor() {
|
||||||
|
super("wp:cNvGraphicFramePr");
|
||||||
|
|
||||||
|
this.root.push(new GraphicFrameLocks());
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,11 @@
|
|||||||
|
import { XmlAttributeComponent } from "file/xml-components";
|
||||||
|
|
||||||
|
export interface IGraphicDataAttributes {
|
||||||
|
uri?: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
export class GraphicDataAttributes extends XmlAttributeComponent<IGraphicDataAttributes> {
|
||||||
|
protected xmlKeys = {
|
||||||
|
uri: "uri",
|
||||||
|
};
|
||||||
|
}
|
17
src/file/drawing/inline/graphic/graphic-data/graphic-data.ts
Normal file
17
src/file/drawing/inline/graphic/graphic-data/graphic-data.ts
Normal file
@ -0,0 +1,17 @@
|
|||||||
|
import { XmlComponent } from "file/xml-components";
|
||||||
|
import { GraphicDataAttributes } from "./graphic-data-attribute";
|
||||||
|
import { Pic } from "./pic";
|
||||||
|
|
||||||
|
export class GraphicData extends XmlComponent {
|
||||||
|
constructor(referenceId: number, x: number, y: number) {
|
||||||
|
super("a:graphicData");
|
||||||
|
|
||||||
|
this.root.push(
|
||||||
|
new GraphicDataAttributes({
|
||||||
|
uri: "http://schemas.openxmlformats.org/drawingml/2006/picture",
|
||||||
|
}),
|
||||||
|
);
|
||||||
|
|
||||||
|
this.root.push(new Pic(referenceId, x, y));
|
||||||
|
}
|
||||||
|
}
|
1
src/file/drawing/inline/graphic/graphic-data/index.ts
Normal file
1
src/file/drawing/inline/graphic/graphic-data/index.ts
Normal file
@ -0,0 +1 @@
|
|||||||
|
export * from "./graphic-data";
|
@ -1,10 +1,9 @@
|
|||||||
import { XmlComponent } from "../../../../../../../../xml-components";
|
import { XmlComponent } from "file/xml-components";
|
||||||
import { Blip } from "./blip";
|
import { Blip } from "./blip";
|
||||||
import { SourceRectangle } from "./source-rectangle";
|
import { SourceRectangle } from "./source-rectangle";
|
||||||
import { Stretch } from "./stretch";
|
import { Stretch } from "./stretch";
|
||||||
|
|
||||||
export class BlipFill extends XmlComponent {
|
export class BlipFill extends XmlComponent {
|
||||||
|
|
||||||
constructor(referenceId: number) {
|
constructor(referenceId: number) {
|
||||||
super("pic:blipFill");
|
super("pic:blipFill");
|
||||||
this.root.push(new Blip(referenceId));
|
this.root.push(new Blip(referenceId));
|
@ -1,21 +1,25 @@
|
|||||||
import { XmlAttributeComponent, XmlComponent } from "../../../../../../../../xml-components";
|
import { XmlAttributeComponent, XmlComponent } from "file/xml-components";
|
||||||
|
|
||||||
interface IBlipProperties {
|
interface IBlipProperties {
|
||||||
embed: string;
|
embed: string;
|
||||||
|
cstate: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
class BlipAttributes extends XmlAttributeComponent<IBlipProperties> {
|
class BlipAttributes extends XmlAttributeComponent<IBlipProperties> {
|
||||||
protected xmlKeys = {
|
protected xmlKeys = {
|
||||||
embed: "r:embed",
|
embed: "r:embed",
|
||||||
|
cstate: "cstate",
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
export class Blip extends XmlComponent {
|
export class Blip extends XmlComponent {
|
||||||
|
|
||||||
constructor(referenceId: number) {
|
constructor(referenceId: number) {
|
||||||
super("a:blip");
|
super("a:blip");
|
||||||
this.root.push(new BlipAttributes({
|
this.root.push(
|
||||||
|
new BlipAttributes({
|
||||||
embed: `rId${referenceId}`,
|
embed: `rId${referenceId}`,
|
||||||
}));
|
cstate: "none",
|
||||||
|
}),
|
||||||
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -1,7 +1,6 @@
|
|||||||
import { XmlComponent } from "../../../../../../../../xml-components";
|
import { XmlComponent } from "file/xml-components";
|
||||||
|
|
||||||
export class SourceRectangle extends XmlComponent {
|
export class SourceRectangle extends XmlComponent {
|
||||||
|
|
||||||
constructor() {
|
constructor() {
|
||||||
super("a:srcRect");
|
super("a:srcRect");
|
||||||
}
|
}
|
@ -1,14 +1,12 @@
|
|||||||
import { XmlComponent } from "../../../../../../../../xml-components";
|
import { XmlComponent } from "file/xml-components";
|
||||||
|
|
||||||
class FillRectangle extends XmlComponent {
|
class FillRectangle extends XmlComponent {
|
||||||
|
|
||||||
constructor() {
|
constructor() {
|
||||||
super("a:fillRect");
|
super("a:fillRect");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export class Stretch extends XmlComponent {
|
export class Stretch extends XmlComponent {
|
||||||
|
|
||||||
constructor() {
|
constructor() {
|
||||||
super("a:stretch");
|
super("a:stretch");
|
||||||
this.root.push(new FillRectangle());
|
this.root.push(new FillRectangle());
|
@ -0,0 +1 @@
|
|||||||
|
export * from "./pic";
|
@ -0,0 +1,10 @@
|
|||||||
|
import { XmlComponent } from "file/xml-components";
|
||||||
|
import { PicLocks } from "./pic-locks/pic-locks";
|
||||||
|
|
||||||
|
export class ChildNonVisualProperties extends XmlComponent {
|
||||||
|
constructor() {
|
||||||
|
super("pic:cNvPicPr");
|
||||||
|
|
||||||
|
this.root.push(new PicLocks());
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,13 @@
|
|||||||
|
import { XmlAttributeComponent } from "file/xml-components";
|
||||||
|
|
||||||
|
export interface IPicLocksAttributes {
|
||||||
|
noChangeAspect?: number;
|
||||||
|
noChangeArrowheads?: number;
|
||||||
|
}
|
||||||
|
|
||||||
|
export class PicLocksAttributes extends XmlAttributeComponent<IPicLocksAttributes> {
|
||||||
|
protected xmlKeys = {
|
||||||
|
noChangeAspect: "noChangeAspect",
|
||||||
|
noChangeArrowheads: "noChangeArrowheads",
|
||||||
|
};
|
||||||
|
}
|
@ -0,0 +1,14 @@
|
|||||||
|
import { XmlComponent } from "file/xml-components";
|
||||||
|
import { PicLocksAttributes } from "./pic-locks-attributes";
|
||||||
|
|
||||||
|
export class PicLocks extends XmlComponent {
|
||||||
|
constructor() {
|
||||||
|
super("a:picLocks");
|
||||||
|
this.root.push(
|
||||||
|
new PicLocksAttributes({
|
||||||
|
noChangeAspect: 1,
|
||||||
|
noChangeArrowheads: 1,
|
||||||
|
}),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,12 @@
|
|||||||
|
import { XmlComponent } from "file/xml-components";
|
||||||
|
import { ChildNonVisualProperties } from "./child-non-visual-pic-properties/child-non-visual-pic-properties";
|
||||||
|
import { NonVisualProperties } from "./non-visual-properties/non-visual-properties";
|
||||||
|
|
||||||
|
export class NonVisualPicProperties extends XmlComponent {
|
||||||
|
constructor() {
|
||||||
|
super("pic:nvPicPr");
|
||||||
|
|
||||||
|
this.root.push(new NonVisualProperties());
|
||||||
|
this.root.push(new ChildNonVisualProperties());
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,15 @@
|
|||||||
|
import { XmlAttributeComponent } from "file/xml-components";
|
||||||
|
|
||||||
|
export interface INonVisualPropertiesAttributes {
|
||||||
|
id?: number;
|
||||||
|
name?: string;
|
||||||
|
descr?: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
export class NonVisualPropertiesAttributes extends XmlAttributeComponent<INonVisualPropertiesAttributes> {
|
||||||
|
protected xmlKeys = {
|
||||||
|
id: "id",
|
||||||
|
name: "name",
|
||||||
|
descr: "desc",
|
||||||
|
};
|
||||||
|
}
|
@ -0,0 +1,16 @@
|
|||||||
|
import { XmlComponent } from "file/xml-components";
|
||||||
|
import { NonVisualPropertiesAttributes } from "./non-visual-properties-attributes";
|
||||||
|
|
||||||
|
export class NonVisualProperties extends XmlComponent {
|
||||||
|
constructor() {
|
||||||
|
super("pic:cNvPr");
|
||||||
|
|
||||||
|
this.root.push(
|
||||||
|
new NonVisualPropertiesAttributes({
|
||||||
|
id: 0,
|
||||||
|
name: "",
|
||||||
|
descr: "",
|
||||||
|
}),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,11 @@
|
|||||||
|
import { XmlAttributeComponent } from "file/xml-components";
|
||||||
|
|
||||||
|
export interface IPicAttributes {
|
||||||
|
xmlns?: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
export class PicAttributes extends XmlAttributeComponent<IPicAttributes> {
|
||||||
|
protected xmlKeys = {
|
||||||
|
xmlns: "xmlns:pic",
|
||||||
|
};
|
||||||
|
}
|
21
src/file/drawing/inline/graphic/graphic-data/pic/pic.ts
Normal file
21
src/file/drawing/inline/graphic/graphic-data/pic/pic.ts
Normal file
@ -0,0 +1,21 @@
|
|||||||
|
// http://officeopenxml.com/drwPic.php
|
||||||
|
import { XmlComponent } from "file/xml-components";
|
||||||
|
import { BlipFill } from "./blip/blip-fill";
|
||||||
|
import { NonVisualPicProperties } from "./non-visual-pic-properties/non-visual-pic-properties";
|
||||||
|
import { PicAttributes } from "./pic-attributes";
|
||||||
|
import { ShapeProperties } from "./shape-properties/shape-properties";
|
||||||
|
|
||||||
|
export class Pic extends XmlComponent {
|
||||||
|
constructor(referenceId: number, x: number, y: number) {
|
||||||
|
super("pic:pic");
|
||||||
|
|
||||||
|
this.root.push(
|
||||||
|
new PicAttributes({
|
||||||
|
xmlns: "http://schemas.openxmlformats.org/drawingml/2006/picture",
|
||||||
|
}),
|
||||||
|
);
|
||||||
|
this.root.push(new NonVisualPicProperties());
|
||||||
|
this.root.push(new BlipFill(referenceId));
|
||||||
|
this.root.push(new ShapeProperties(x, y));
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,13 @@
|
|||||||
|
import { XmlAttributeComponent } from "file/xml-components";
|
||||||
|
|
||||||
|
export interface IExtentsAttributes {
|
||||||
|
cx?: number;
|
||||||
|
cy?: number;
|
||||||
|
}
|
||||||
|
|
||||||
|
export class ExtentsAttributes extends XmlAttributeComponent<IExtentsAttributes> {
|
||||||
|
protected xmlKeys = {
|
||||||
|
cx: "cx",
|
||||||
|
cy: "cy",
|
||||||
|
};
|
||||||
|
}
|
@ -0,0 +1,16 @@
|
|||||||
|
// http://officeopenxml.com/drwSp-size.php
|
||||||
|
import { XmlComponent } from "file/xml-components";
|
||||||
|
import { ExtentsAttributes } from "./extents-attributes";
|
||||||
|
|
||||||
|
export class Extents extends XmlComponent {
|
||||||
|
constructor(x: number, y: number) {
|
||||||
|
super("a:ext");
|
||||||
|
|
||||||
|
this.root.push(
|
||||||
|
new ExtentsAttributes({
|
||||||
|
cx: x,
|
||||||
|
cy: y,
|
||||||
|
}),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,13 @@
|
|||||||
|
// http://officeopenxml.com/drwSp-size.php
|
||||||
|
import { XmlComponent } from "file/xml-components";
|
||||||
|
import { Extents } from "./extents/extents";
|
||||||
|
import { Offset } from "./offset/off";
|
||||||
|
|
||||||
|
export class Form extends XmlComponent {
|
||||||
|
constructor(x: number, y: number) {
|
||||||
|
super("a:xfrm");
|
||||||
|
|
||||||
|
this.root.push(new Extents(x, y));
|
||||||
|
this.root.push(new Offset());
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1 @@
|
|||||||
|
export * from "./form";
|
@ -0,0 +1,13 @@
|
|||||||
|
import { XmlAttributeComponent } from "file/xml-components";
|
||||||
|
|
||||||
|
export interface IOffsetAttributes {
|
||||||
|
x?: number;
|
||||||
|
y?: number;
|
||||||
|
}
|
||||||
|
|
||||||
|
export class OffsetAttributes extends XmlAttributeComponent<IOffsetAttributes> {
|
||||||
|
protected xmlKeys = {
|
||||||
|
x: "x",
|
||||||
|
y: "y",
|
||||||
|
};
|
||||||
|
}
|
@ -0,0 +1,16 @@
|
|||||||
|
// http://officeopenxml.com/drwSp-size.php
|
||||||
|
import { XmlComponent } from "file/xml-components";
|
||||||
|
import { OffsetAttributes } from "./off-attributes";
|
||||||
|
|
||||||
|
export class Offset extends XmlComponent {
|
||||||
|
constructor() {
|
||||||
|
super("a:off");
|
||||||
|
|
||||||
|
this.root.push(
|
||||||
|
new OffsetAttributes({
|
||||||
|
x: 0,
|
||||||
|
y: 0,
|
||||||
|
}),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,7 @@
|
|||||||
|
import { XmlComponent } from "file/xml-components";
|
||||||
|
|
||||||
|
export class NoFill extends XmlComponent {
|
||||||
|
constructor() {
|
||||||
|
super("a:noFill");
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,7 @@
|
|||||||
|
import { XmlComponent } from "file/xml-components";
|
||||||
|
|
||||||
|
export class NoFill extends XmlComponent {
|
||||||
|
constructor() {
|
||||||
|
super("a:noFill");
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,11 @@
|
|||||||
|
// http://officeopenxml.com/drwSp-outline.php
|
||||||
|
import { XmlComponent } from "file/xml-components";
|
||||||
|
import { NoFill } from "./no-fill";
|
||||||
|
|
||||||
|
export class Outline extends XmlComponent {
|
||||||
|
constructor() {
|
||||||
|
super("a:ln");
|
||||||
|
|
||||||
|
this.root.push(new NoFill());
|
||||||
|
}
|
||||||
|
}
|
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user