Compare commits

...

57 Commits
2.0.1 ... 3.0.0

Author SHA1 Message Date
492face7ab 3.0.0 2017-09-17 00:20:18 +01:00
b6351f0260 Merge branch 'jacwright-indent-bc' 2017-09-17 00:09:57 +01:00
3a7f9053b9 Allow indent to use other options than left and hanging
This is a breaking change. Existing code using indent will break when padding in the number for left.
2017-09-16 17:05:40 -06:00
19b122684c Add lint to Travis
Fix linting
2017-09-17 00:01:09 +01:00
72e89cfc3c Move tests to respective folders as .spec
This is to keep to standards
2017-09-17 00:00:41 +01:00
5ae02c3342 Merge pull request #43 from jacwright/default-run-styles
Making it easier to work with default styles
2017-09-16 17:48:37 +01:00
258adba94c Version bump 2017-09-16 17:48:15 +01:00
190208d5df Making it easier to work with default styles
Adds the likely common styles, font and size, to be defined in defaults.
2017-09-16 08:24:15 -06:00
32cda4dfb3 Merge pull request #42 from jacwright/patch-1-test
Fix tests
2017-09-15 16:09:18 +01:00
b2c3dd2f7b Fix tests 2017-09-15 09:05:28 -06:00
58eca3ff5b Merge pull request #41 from jacwright/patch-1
Fix page/thematic breaks
2017-09-15 15:57:22 +01:00
d5c04f9042 Pin typescript to 2.4.1 2017-09-15 15:56:21 +01:00
67ea7c95de Just pagebreak, update test 2017-09-15 08:37:57 -06:00
e57fd8fc57 Fix page/thematic breaks
These items are not paragraph properties, but part of the content of the paragraph.
2017-09-15 08:25:43 -06:00
411c0dadb5 Add table demo 2017-07-29 01:58:29 +01:00
ee81f3c502 Version bump 2017-07-29 01:26:34 +01:00
8263b93c36 Add third demo 2017-07-29 01:26:04 +01:00
be709d082c Export formatting from paragraph folder 2017-07-29 01:15:33 +01:00
70c4e89a65 Version bump 2017-07-08 21:37:02 +01:00
8f632d4ecd Made XmlableObject non ambient typings to fix typescript problem 2017-07-08 20:45:19 +01:00
6784dc1f3d Updated archiver types 2017-07-08 01:24:25 +01:00
fd63a30298 Updated definitions 2017-07-07 16:51:22 +01:00
b0a29e26c9 Version bump 2017-07-07 14:36:34 +01:00
8826fb010d Added types to package json 2017-07-07 14:34:03 +01:00
97101adb10 Enabled declarations in tsconfig to be true 2017-07-07 14:31:08 +01:00
2ec171d4a8 Used my updated typings for archiver 1.3 2017-05-09 18:03:31 +01:00
8876bb1fea updated readme about demos 2017-04-17 19:53:53 +01:00
96ca9d9c23 commented out the rm 2017-04-17 16:36:56 +01:00
74a65f02fa remove exit code 2017-04-17 16:07:28 +01:00
339c017940 edited rm function 2017-04-17 15:41:03 +01:00
969b52ae05 added nojekyll to gh-pages 2017-04-17 13:24:43 +01:00
eb8f0f4033 added debugging to deployment 2017-04-17 13:05:02 +01:00
d7229eb049 removed rimraf 2017-04-16 12:41:24 +01:00
644819ed81 added deployment keys and scripts 2017-04-16 12:22:50 +01:00
96fd61d3e4 using stable version of node 2017-04-16 02:25:44 +01:00
b96cfe7b19 git fetch added 2017-04-16 01:29:29 +01:00
d0e7c97a88 added commit message with merge with gh pages 2017-04-16 01:18:22 +01:00
0ede54cfdc added travis doc deployment solution 2017-04-16 01:12:42 +01:00
5be1163549 remove docs in gitignore 2017-04-16 01:07:11 +01:00
580f6eb633 fixed tests 2017-04-16 00:44:35 +01:00
321be35918 added docs in gitignore 2017-04-16 00:30:27 +01:00
45a18742d7 moved documentation to gh-pages branch 2017-04-16 00:22:29 +01:00
7e81da404a updated readme 2017-04-16 00:09:07 +01:00
6c2abb4abc added typedoc generated docs 2017-04-16 00:07:16 +01:00
e8b0dbf93b added docs ignore to npmignore file 2017-04-16 00:04:29 +01:00
e59c255d85 added type to pack param 2017-04-15 23:45:27 +01:00
17b28cb724 fixed more linting issues 2017-04-15 20:11:54 +01:00
410152441b fixed tslinting issues 2017-04-15 17:54:47 +01:00
dfff4b96bd updated tslint to 5.1.0 2017-04-15 17:47:29 +01:00
72cb75a486 added comma 2017-04-15 17:46:56 +01:00
53fe1dd988 added typedoc support for generating documentation 2017-04-15 17:46:11 +01:00
043219f005 Merge pull request #32 from felipeochoa/keep-lines
add keepLines and keepNext support for paragraph formatting
2017-04-15 17:41:11 +01:00
0453f28951 add keepLines and keepNext support for paragraph formatting
This commit adds it to the three places where paragraph formatting can
be applied right now (directly on the paragraph, paragraph styles, and
bullets/numbering styles). I'm separately adding an entry to the wiki
regarding what these methods do (widow/orphan control)
2017-04-14 21:13:11 +02:00
94716e081b Merge pull request #31 from felipeochoa/spacing-bugfix
Spacing bugfix
2017-04-14 17:30:54 +01:00
30f826fd3d made a mini app which you can select the demo you want from a list with an interactive prompt. 2017-04-14 15:48:12 +01:00
99b7a03b8a update demo2 to test space preservation 2017-04-14 11:09:08 +02:00
b1c8b2beb8 add xml:space="preserve" to text runs
In MS Word 2015 (and possibly others), leading and trailing spaces are
ignored in text runs. This means that calling TextRun with
leading/trailing space would result in a document that didn't include
those spaces. The fix here (per http://officeopenxml.com/WPtext.php)
is to include an extra attribute on the "w:t" element that forces word
to recognize those spaces.
2017-04-14 11:08:19 +02:00
78 changed files with 569 additions and 193 deletions

View File

@ -38,3 +38,6 @@ build-tests
# vscode # vscode
.vscode .vscode
# docs
docs

View File

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

View File

@ -26,12 +26,14 @@ $ npm install --save docx
$ npm run demo $ npm run demo
``` ```
will run the demo app in the `demo` folder, which creates a file called "My Document.docx" in the root of the project will run the demo selector app in the `demo` folder. It will prompt you to select a demo number, which will run a demo from that folder.
## Guide ## Guide
Please refer to [the Wiki](https://github.com/dolanmiu/docx/wiki) for details on how to use this library, examples and much more! Please refer to [the Wiki](https://github.com/dolanmiu/docx/wiki) for details on how to use this library, examples and much more!
Full documentation can be found here: [http://dolanmiu.github.io/docx](http://dolanmiu.github.io/docx)
## Simple Usage ## Simple Usage
```js ```js

View File

@ -64,7 +64,11 @@ doc.createParagraph()
doc.createParagraph('An aside, in light gray italics and indented').style('aside'); doc.createParagraph('An aside, in light gray italics and indented').style('aside');
doc.createParagraph('This is normal, but well-spaced text').style('wellSpaced'); doc.createParagraph('This is normal, but well-spaced text').style('wellSpaced');
doc.createParagraph('This is normal'); const para = doc.createParagraph();
para.createTextRun('This is a bold run,').bold();
para.createTextRun(' switching to normal ');
para.createTextRun('and then underlined ').underline();
para.createTextRun('and back to normal.');
const exporter = new docx.LocalPacker(doc, styles, undefined, numbering); const exporter = new docx.LocalPacker(doc, styles, undefined, numbering);
exporter.pack('test.docx'); exporter.pack('test.docx');

35
demo/demo3.js Normal file
View File

@ -0,0 +1,35 @@
const docx = require('../build');
var doc = new docx.Document();
const numbering = new docx.Numbering();
const abstractNum = numbering.createAbstractNumbering();
abstractNum.createLevel(0, "upperRoman", "%1", "start")
.addParagraphProperty(new docx.Indent(720, 260));
abstractNum.createLevel(1, "decimal", "%2.", "start")
.addParagraphProperty(new docx.Indent(1440, 980));
abstractNum.createLevel(2, "lowerLetter", "%3)", "start")
.addParagraphProperty(new docx.Indent(2160, 1700));
const concrete = numbering.createConcreteNumbering(abstractNum);
var topLevelP = new docx.Paragraph("Hey you");
var subP = new docx.Paragraph("What's up fam");
var secondSubP = new docx.Paragraph("Hello World 2");
var subSubP = new docx.Paragraph("Yeah boi");
topLevelP.setNumbering(concrete, 0);
subP.setNumbering(concrete, 1);
secondSubP.setNumbering(concrete, 1);
subSubP.setNumbering(concrete, 2);
doc.addParagraph(topLevelP);
doc.addParagraph(subP);
doc.addParagraph(secondSubP);
doc.addParagraph(subSubP);
var exporter = new docx.LocalPacker(doc);
exporter.pack('My Document');
console.log('Document created succesfully at project root!');

12
demo/demo4.js Normal file
View File

@ -0,0 +1,12 @@
const docx = require('../build');
var doc = new docx.Document();
const table = doc.createTable(4, 4);
table.getCell(2, 2).addContent(new docx.Paragraph('Hello'));
var exporter = new docx.LocalPacker(doc);
exporter.pack('My Document');
console.log('Document created succesfully at project root!');

29
demo/index.js Normal file
View File

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

68
deploy-docs.sh Normal file
View File

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

BIN
deploy-key.enc Normal file

Binary file not shown.

View File

@ -1,6 +1,6 @@
{ {
"name": "docx", "name": "docx",
"version": "2.0.1", "version": "3.0.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": {
@ -9,8 +9,8 @@
"prepublishOnly": "npm run build", "prepublishOnly": "npm run build",
"lint": "tslint --project ./ts", "lint": "tslint --project ./ts",
"build": "rimraf ./build && tsc -p ts", "build": "rimraf ./build && tsc -p ts",
"demo": "npm run build && node ./demo/demo.js", "demo": "npm run build && node ./demo",
"demo2": "npm run build && node ./demo/demo2.js" "typedoc": "typedoc --out docs/ ts/ --module commonjs --target ES6 --disableOutputCheck"
}, },
"files": [ "files": [
"ts", "ts",
@ -32,8 +32,9 @@
"officegen", "officegen",
"clippy" "clippy"
], ],
"types": "./build/index.d.ts",
"dependencies": { "dependencies": {
"@types/archiver": "^0.15.37", "@types/archiver": "^1.3.4",
"@types/express": "^4.0.35", "@types/express": "^4.0.35",
"archiver": "^1.3.0", "archiver": "^1.3.0",
"xml": "^1.0.1" "xml": "^1.0.1"
@ -49,8 +50,11 @@
"@types/mocha": "^2.2.39", "@types/mocha": "^2.2.39",
"chai": "^3.5.0", "chai": "^3.5.0",
"mocha": "^3.2.0", "mocha": "^3.2.0",
"prompt": "^1.0.0",
"rimraf": "^2.5.2", "rimraf": "^2.5.2",
"tslint": "^4.5.1", "shelljs": "^0.7.7",
"typescript": "^2.2.1" "tslint": "^5.1.0",
"typedoc": "^0.5.10",
"typescript": "2.4.1"
} }
} }

View File

@ -1,11 +1,12 @@
import { assert } from "chai"; import { assert } from "chai";
import { Body } from "../../../docx/document/body";
import { Columns } from "../../../docx/document/body/columns"; import { Utility } from "../../../tests/utility";
import { DocumentGrid } from "../../../docx/document/body/doc-grid"; import { Body } from "./";
import { PageMargin } from "../../../docx/document/body/page-margin"; import { Columns } from "./columns";
import { PageSize } from "../../../docx/document/body/page-size"; import { DocumentGrid } from "./doc-grid";
import { SectionProperties } from "../../../docx/document/body/section-properties"; import { PageMargin } from "./page-margin";
import { Utility } from "../../utility"; import { PageSize } from "./page-size";
import { SectionProperties } from "./section-properties";
describe("Body", () => { describe("Body", () => {
let body: Body; let body: Body;

View File

@ -1,6 +1,6 @@
import { XmlAttributeComponent } from "../xml-components"; import { XmlAttributeComponent } from "../xml-components";
interface IDocumentAttributesProperties { export interface IDocumentAttributesProperties {
wpc?: string; wpc?: string;
mc?: string; mc?: string;
o?: string; o?: string;

View File

@ -1,6 +1,7 @@
import { assert, expect } from "chai"; import { assert, expect } from "chai";
import * as docx from "../../../docx";
import { Formatter } from "../../../export/formatter"; import * as docx from "../../";
import { Formatter } from "../../export/formatter";
describe("Document", () => { describe("Document", () => {
let document: docx.Document; let document: docx.Document;
@ -41,7 +42,7 @@ describe("Document", () => {
expect(body[0]).to.have.property("w:p").which.includes({ expect(body[0]).to.have.property("w:p").which.includes({
"w:r": [ "w:r": [
{"w:rPr": []}, {"w:rPr": []},
{"w:t": ["sample paragraph text"]}, {"w:t": [{_attr: {"xml:space": "preserve"}}, "sample paragraph text"]},
], ],
}); });
}); });

View File

@ -1,5 +1,5 @@
export { Document } from "./document"; export { Document } from "./document";
export { Paragraph } from "./paragraph"; export * from "./paragraph";
export { Run } from "./run"; export { Run } from "./run";
export { TextRun } from "./run/text-run"; export { TextRun } from "./run/text-run";
export { PictureRun } from "./run/picture-run"; export { PictureRun } from "./run/picture-run";

View File

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

View File

@ -1,6 +1,7 @@
import { assert } from "chai"; import { assert } from "chai";
import { ThematicBreak } from "../../../docx/paragraph/border";
import { Utility } from "../../utility"; import { Utility } from "../../tests/utility";
import { ThematicBreak } from "./border";
describe("Border", () => { describe("Border", () => {
// TODO: Need tests here // TODO: Need tests here

View File

@ -1,6 +1,7 @@
export { Alignment } from "./alignment"; export { Alignment } from "./alignment";
export { ThematicBreak } from "./border"; export { ThematicBreak } from "./border";
export { Indent } from "./indent"; export { Indent } from "./indent";
export { KeepLines, KeepNext } from "./keep";
export { PageBreak } from "./page-break"; export { PageBreak } from "./page-break";
export { ParagraphProperties } from "./properties"; export { ParagraphProperties } from "./properties";
export { ISpacingProperties, Spacing } from "./spacing"; export { ISpacingProperties, Spacing } from "./spacing";

View File

@ -3,22 +3,25 @@ import { XmlAttributeComponent, XmlComponent } from "../xml-components";
interface IIndentAttributesProperties { interface IIndentAttributesProperties {
left?: number; left?: number;
hanging?: number; hanging?: number;
firstLine?: number;
start?: number;
end?: number;
} }
class IndentAttributes extends XmlAttributeComponent<IIndentAttributesProperties> { class IndentAttributes extends XmlAttributeComponent<IIndentAttributesProperties> {
protected xmlKeys = { protected xmlKeys = {
left: "w:left", left: "w:left",
hanging: "w:hanging", hanging: "w:hanging",
firstLine: "w:firstLine",
start: "w:start",
end: "w:end",
}; };
} }
export class Indent extends XmlComponent { export class Indent extends XmlComponent {
constructor(left: number, hanging?: number) { constructor(attrs: object) {
super("w:ind"); super("w:ind");
this.root.push(new IndentAttributes({ this.root.push(new IndentAttributes(attrs));
left: left,
hanging: hanging,
}));
} }
} }

View File

@ -8,6 +8,7 @@ import { XmlComponent } from "../xml-components";
import { Alignment } from "./alignment"; import { Alignment } from "./alignment";
import { ThematicBreak } from "./border"; import { ThematicBreak } from "./border";
import { Indent } from "./indent"; import { Indent } from "./indent";
import { KeepLines, KeepNext } from "./keep";
import { PageBreak } from "./page-break"; import { PageBreak } from "./page-break";
import { ParagraphProperties } from "./properties"; import { ParagraphProperties } from "./properties";
import { ISpacingProperties, Spacing } from "./spacing"; import { ISpacingProperties, Spacing } from "./spacing";
@ -15,6 +16,8 @@ import { Style } from "./style";
import { LeftTabStop, MaxRightTabStop } from "./tab-stop"; import { LeftTabStop, MaxRightTabStop } from "./tab-stop";
import { NumberProperties } from "./unordered-list"; import { NumberProperties } from "./unordered-list";
export * from "./formatting";
export class Paragraph extends XmlComponent { export class Paragraph extends XmlComponent {
private properties: ParagraphProperties; private properties: ParagraphProperties;
@ -100,7 +103,7 @@ export class Paragraph extends XmlComponent {
} }
public pageBreak(): Paragraph { public pageBreak(): Paragraph {
this.properties.push(new PageBreak()); this.root.push(new PageBreak());
return this; return this;
} }
@ -131,13 +134,23 @@ export class Paragraph extends XmlComponent {
return this; return this;
} }
public indent(start: number, hanging?: number): Paragraph { public indent(attrs: object): Paragraph {
this.properties.push(new Indent(start, hanging)); this.properties.push(new Indent(attrs));
return this; return this;
} }
public spacing(params: ISpacingProperties): Paragraph { public spacing(params: ISpacingProperties): Paragraph {
this.properties.push(new Spacing(params)); this.properties.push(new Spacing(params));
return this; return this;
}; }
public keepNext(): Paragraph {
this.properties.push(new KeepNext());
return this;
}
public keepLines(): Paragraph {
this.properties.push(new KeepLines());
return this;
}
} }

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

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

View File

@ -1,6 +1,7 @@
import { assert } from "chai"; import { assert } from "chai";
import { PageBreak } from "../../../docx/paragraph/page-break";
import { Utility } from "../../utility"; import { Utility } from "../../tests/utility";
import { PageBreak } from "./page-break";
describe("PageBreak", () => { describe("PageBreak", () => {
let pageBreak: PageBreak; let pageBreak: PageBreak;

View File

@ -1,7 +1,8 @@
import { assert, expect } from "chai"; import { assert, expect } from "chai";
import * as docx from "../../../docx";
import { Formatter } from "../../../export/formatter"; import * as docx from "../../docx";
import { Numbering } from "../../../numbering"; import { Formatter } from "../../export/formatter";
import { Numbering } from "../../numbering";
describe("Paragraph", () => { describe("Paragraph", () => {
let paragraph: docx.Paragraph; let paragraph: docx.Paragraph;
@ -39,7 +40,7 @@ describe("Paragraph", () => {
expect(tree).to.be.an("array").which.includes({ expect(tree).to.be.an("array").which.includes({
"w:r": [ "w:r": [
{"w:rPr": []}, {"w:rPr": []},
{"w:t": ["this is a test run"]}, {"w:t": [{_attr: {"xml:space": "preserve"}}, "this is a test run"]},
], ],
}); });
}); });
@ -144,13 +145,13 @@ describe("Paragraph", () => {
const tree = new Formatter().format(paragraph); const tree = new Formatter().format(paragraph);
expect(tree).to.deep.equal({ expect(tree).to.deep.equal({
"w:p": [{ "w:p": [{
"w:pPr": [{ "w:pPr": [],
}, {
"w:r": [ "w:r": [
{"w:rPr": []}, {"w:rPr": []},
{"w:br": [{_attr: {"w:type": "page"}}]}, {"w:br": [{_attr: {"w:type": "page"}}]},
], ],
}], }],
}],
}); });
}); });
}); });
@ -240,7 +241,7 @@ describe("Paragraph", () => {
describe("#indent", () => { describe("#indent", () => {
it("should set the paragraph indent to the given values", () => { it("should set the paragraph indent to the given values", () => {
paragraph.indent(720); paragraph.indent({ left: 720 });
const tree = new Formatter().format(paragraph); const tree = new Formatter().format(paragraph);
expect(tree).to.deep.equal({ expect(tree).to.deep.equal({
"w:p": [ "w:p": [
@ -269,4 +270,24 @@ describe("Paragraph", () => {
}); });
}); });
}); });
describe("#keepLines", () => {
it("should set the paragraph keepLines sub-component", () => {
paragraph.keepLines();
const tree = new Formatter().format(paragraph);
expect(tree).to.deep.equal({
"w:p": [{"w:pPr": [{"w:keepLines": []}]}],
});
});
});
describe("#keepNext", () => {
it("should set the paragraph keepNext sub-component", () => {
paragraph.keepNext();
const tree = new Formatter().format(paragraph);
expect(tree).to.deep.equal({
"w:p": [{"w:pPr": [{"w:keepNext": []}]}],
});
});
});
}); });

View File

@ -1,6 +1,7 @@
import { expect } from "chai"; import { expect } from "chai";
import { Spacing } from "../../../docx/paragraph/spacing";
import { Formatter } from "../../../export/formatter"; import { Formatter } from "../../export/formatter";
import { Spacing } from "./spacing";
describe("Spacing", () => { describe("Spacing", () => {
describe("#constructor", () => { describe("#constructor", () => {

View File

@ -1,6 +1,7 @@
import { assert } from "chai"; import { assert } from "chai";
import { Style } from "../../../docx/paragraph/style";
import { Utility } from "../../utility"; import { Utility } from "../../tests/utility";
import { Style } from "./style";
describe("ParagraphStyle", () => { describe("ParagraphStyle", () => {
let style: Style; let style: Style;

View File

@ -1,6 +1,7 @@
import { assert } from "chai"; import { assert } from "chai";
import { LeftTabStop, MaxRightTabStop } from "../../../docx/paragraph/tab-stop";
import { Utility } from "../../utility"; import { Utility } from "../../tests/utility";
import { LeftTabStop, MaxRightTabStop } from "./tab-stop";
describe("LeftTabStop", () => { describe("LeftTabStop", () => {
let tabStop: LeftTabStop; let tabStop: LeftTabStop;

View File

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

View File

@ -1,6 +1,7 @@
import { assert } from "chai"; import { assert } from "chai";
import { NumberProperties } from "../../../docx/paragraph/unordered-list";
import { Utility } from "../../utility"; import { Utility } from "../../tests/utility";
import { NumberProperties } from "./unordered-list";
describe("NumberProperties", () => { describe("NumberProperties", () => {
let numberProperties: NumberProperties; let numberProperties: NumberProperties;

View File

@ -1,6 +1,7 @@
import { assert } from "chai"; import { assert } from "chai";
import { Break } from "../../../docx/run/break";
import { Utility } from "../../utility"; import { Utility } from "../../tests/utility";
import { Break } from "./break";
describe("Break", () => { describe("Break", () => {
let currentBreak: Break; let currentBreak: Break;

View File

@ -1,7 +1,8 @@
import { assert } from "chai"; import { assert } from "chai";
import * as fs from "fs"; import * as fs from "fs";
import { Drawing } from "../../../../docx/run/run-components/drawing";
import { Utility } from "../../../utility"; import { Utility } from "../../../../tests/utility";
import { Drawing } from "./";
describe("Drawing", () => { describe("Drawing", () => {
let currentBreak: Drawing; let currentBreak: Drawing;
@ -20,7 +21,7 @@ describe("Drawing", () => {
it("should create a Drawing with correct root key", () => { it("should create a Drawing with correct root key", () => {
const newJson = Utility.jsonify(currentBreak); const newJson = Utility.jsonify(currentBreak);
assert.equal(newJson.rootKey, "w:drawing"); assert.equal(newJson.rootKey, "w:drawing");
console.log(JSON.stringify(newJson, null, 2)); // console.log(JSON.stringify(newJson, null, 2));
}); });
}); });
}); });

View File

@ -1,7 +1,6 @@
import { XmlAttributeComponent, XmlComponent } from "../../../../../xml-components"; import { XmlAttributeComponent, XmlComponent } from "../../../../../xml-components";
import { GraphicData } from "./graphic-data"; import { GraphicData } from "./graphic-data";
interface IGraphicProperties { interface IGraphicProperties {
a: string; a: string;
} }

View File

@ -0,0 +1,23 @@
import { expect } from "chai";
import { Formatter } from "../../../export/formatter";
import { Text } from "./text";
describe("Text", () => {
describe("#constructor", () => {
it("creates an empty text run if no text is given", () => {
const t = new Text("");
const f = new Formatter().format(t);
expect(f).to.deep.equal({"w:t": [{_attr: {"xml:space": "preserve"}}]});
});
it("adds the passed in text to the component", () => {
const t = new Text(" this is\n text");
const f = new Formatter().format(t);
expect(f).to.deep.equal({"w:t": [
{_attr: {"xml:space": "preserve"}},
" this is\n text",
]});
});
});
});

View File

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

View File

@ -1,6 +1,7 @@
import { expect } from "chai"; import { expect } from "chai";
import { RunFonts } from "../../../docx/run/run-fonts";
import { Formatter } from "../../../export/formatter"; import { Formatter } from "../../export/formatter";
import { RunFonts } from "./run-fonts";
describe("RunFonts", () => { describe("RunFonts", () => {

View File

@ -1,7 +1,8 @@
import { assert, expect } from "chai"; import { assert, expect } from "chai";
import { Run } from "../../../docx/run";
import { Formatter } from "../../../export/formatter"; import { Formatter } from "../../export/formatter";
import { Utility } from "../../utility"; import { Utility } from "../../tests/utility";
import { Run } from "./";
describe("Run", () => { describe("Run", () => {
let run: Run; let run: Run;

View File

@ -1,6 +1,7 @@
import { assert } from "chai"; import { assert } from "chai";
import { SubScript, SuperScript } from "../../../docx/run/script";
import { Utility } from "../../utility"; import { Utility } from "../../tests/utility";
import { SubScript, SuperScript } from "./script";
describe("SubScript", () => { describe("SubScript", () => {
let subScript: SubScript; let subScript: SubScript;

View File

@ -1,6 +1,6 @@
import { Attributes, XmlComponent } from "../xml-components"; import { Attributes, XmlComponent } from "../xml-components";
abstract class VerticalAlign extends XmlComponent { export abstract class VerticalAlign extends XmlComponent {
constructor(type: string) { constructor(type: string) {
super("w:vertAlign"); super("w:vertAlign");

View File

@ -1,6 +1,7 @@
import { assert } from "chai"; import { assert } from "chai";
import { DoubleStrike, Strike } from "../../../docx/run/formatting";
import { Utility } from "../../utility"; import { Utility } from "../../tests/utility";
import { DoubleStrike, Strike } from "./formatting";
describe("Strike", () => { describe("Strike", () => {
let strike: Strike; let strike: Strike;

View File

@ -1,6 +1,7 @@
import { assert } from "chai"; import { assert } from "chai";
import { Tab } from "../../../docx/run/tab";
import { Utility } from "../../utility"; import { Utility } from "../../tests/utility";
import { Tab } from "./tab";
describe("Tab", () => { describe("Tab", () => {
let tab: Tab; let tab: Tab;

View File

@ -0,0 +1,20 @@
import { expect } from "chai";
import { Formatter } from "../../export/formatter";
import { TextRun } from "./text-run";
describe("TextRun", () => {
let run: TextRun;
describe("#constructor()", () => {
it("should add text into run", () => {
run = new TextRun("test");
const f = new Formatter().format(run);
expect(f).to.deep.equal({"w:r": [
{"w:rPr": []},
{"w:t": [{_attr: {"xml:space": "preserve"}}, "test"]},
]});
});
});
});

View File

@ -1,7 +1,8 @@
import { assert, expect } from "chai"; import { assert, expect } from "chai";
import * as u from "../../../docx/run/underline";
import { Formatter } from "../../../export/formatter"; import { Formatter } from "../../export/formatter";
import { Utility } from "../../utility"; import { Utility } from "../../tests/utility";
import * as u from "./underline";
describe("Underline", () => { describe("Underline", () => {

View File

@ -1,6 +1,6 @@
import { Attributes, XmlComponent } from "../xml-components"; import { Attributes, XmlComponent } from "../xml-components";
abstract class BaseUnderline extends XmlComponent { export abstract class BaseUnderline extends XmlComponent {
constructor(underlineType: string, color?: string) { constructor(underlineType: string, color?: string) {
super("w:u"); super("w:u");

View File

@ -1,6 +1,7 @@
import { expect } from "chai"; import { expect } from "chai";
import { GridCol, TableGrid } from "../../../docx/table/grid";
import { Formatter } from "../../../export/formatter"; import { Formatter } from "../../export/formatter";
import { GridCol, TableGrid } from "./grid";
describe("GridCol", () => { describe("GridCol", () => {
describe("#constructor", () => { describe("#constructor", () => {

View File

@ -1,8 +1,8 @@
import { Paragraph } from "../paragraph"; import { Paragraph } from "../paragraph";
import { XmlComponent } from "../xml-components"; import { XmlComponent } from "../xml-components";
import { IXmlableObject } from "../xml-components/xmlable-object";
import { TableGrid } from "./grid"; import { TableGrid } from "./grid";
import { TableProperties, widthTypes } from "./properties"; import { TableProperties, WidthTypes } from "./properties";
export class Table extends XmlComponent { export class Table extends XmlComponent {
private properties: TableProperties; private properties: TableProperties;
@ -51,7 +51,7 @@ export class Table extends XmlComponent {
return this.getRow(row).getCell(col); return this.getRow(row).getCell(col);
} }
public setWidth(type: widthTypes, width: number | string): Table { public setWidth(type: WidthTypes, width: number | string): Table {
this.properties.setWidth(type, width); this.properties.setWidth(type, width);
return this; return this;
} }
@ -62,7 +62,7 @@ export class Table extends XmlComponent {
} }
} }
class TableRow extends XmlComponent { export class TableRow extends XmlComponent {
private properties: TableRowProperties; private properties: TableRowProperties;
private cells: TableCell[]; private cells: TableCell[];
@ -79,13 +79,13 @@ class TableRow extends XmlComponent {
} }
} }
class TableRowProperties extends XmlComponent { export class TableRowProperties extends XmlComponent {
constructor() { constructor() {
super("w:trPr"); super("w:trPr");
} }
} }
class TableCell extends XmlComponent { export class TableCell extends XmlComponent {
private properties: TableCellProperties; private properties: TableCellProperties;
constructor() { constructor() {
@ -99,7 +99,7 @@ class TableCell extends XmlComponent {
return this; return this;
} }
public prepForXml(): object { public prepForXml(): IXmlableObject {
// Cells must end with a paragraph // Cells must end with a paragraph
const retval = super.prepForXml(); const retval = super.prepForXml();
const content = retval["w:tc"]; const content = retval["w:tc"];
@ -116,7 +116,7 @@ class TableCell extends XmlComponent {
} }
} }
class TableCellProperties extends XmlComponent { export class TableCellProperties extends XmlComponent {
constructor() { constructor() {
super("w:tcPr"); super("w:tcPr");
} }

View File

@ -1,6 +1,7 @@
import { expect } from "chai"; import { expect } from "chai";
import { TableProperties } from "../../../docx/table/properties";
import { Formatter } from "../../../export/formatter"; import { Formatter } from "../../export/formatter";
import { TableProperties } from "./properties";
describe("TableProperties", () => { describe("TableProperties", () => {
describe("#constructor", () => { describe("#constructor", () => {

View File

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

View File

@ -1,7 +1,9 @@
/* tslint:disable:no-unused-expression */
import { expect } from "chai"; import { expect } from "chai";
import { Paragraph } from "../../../docx/paragraph";
import { Table } from "../../../docx/table"; import { Formatter } from "../../export/formatter";
import { Formatter } from "../../../export/formatter"; import { Paragraph } from "../paragraph";
import { Table } from "./";
describe("Table", () => { describe("Table", () => {
describe("#constructor", () => { describe("#constructor", () => {
@ -36,7 +38,7 @@ describe("Table", () => {
{"w:tcPr": []}, {"w:tcPr": []},
{"w:p": [ {"w:p": [
{"w:pPr": []}, {"w:pPr": []},
{"w:r": [{"w:rPr": []}, {"w:t": [c]}]}, {"w:r": [{"w:rPr": []}, {"w:t": [{_attr: {"xml:space": "preserve"}}, c]}]},
]}, ]},
]}); ]});
expect(tree).to.deep.equal({ expect(tree).to.deep.equal({
@ -65,7 +67,7 @@ describe("Table", () => {
{"w:tcPr": []}, {"w:tcPr": []},
{"w:p": [ {"w:p": [
{"w:pPr": []}, {"w:pPr": []},
{"w:r": [{"w:rPr": []}, {"w:t": [c]}]}, {"w:r": [{"w:rPr": []}, {"w:t": [{_attr: {"xml:space": "preserve"}}, c]}]},
]}, ]},
]}); ]});
expect(tree).to.deep.equal({ expect(tree).to.deep.equal({
@ -153,7 +155,7 @@ describe("Table", () => {
{"w:tcPr": []}, {"w:tcPr": []},
{"w:p": [ {"w:p": [
{"w:pPr": []}, {"w:pPr": []},
{"w:r": [{"w:rPr": []}, {"w:t": ["Hello"]}]}, {"w:r": [{"w:rPr": []}, {"w:t": [{_attr: {"xml:space": "preserve"}}, "Hello"]}]},
]}, ]},
], ],
}); });
@ -175,7 +177,10 @@ describe("Table", () => {
{"w:tcPr": []}, {"w:tcPr": []},
{"w:p": [ {"w:p": [
{"w:pPr": []}, {"w:pPr": []},
{"w:r": [{"w:rPr": []}, {"w:t": ["Test paragraph"]}]}, {"w:r": [
{"w:rPr": []},
{"w:t": [{_attr: {"xml:space": "preserve"}}, "Test paragraph"]},
]},
]}, ]},
], ],
}); });

View File

@ -1,5 +1,6 @@
import { assert } from "chai"; import { assert } from "chai";
import { Attributes } from "../../../docx/xml-components";
import { Attributes } from "./";
describe("Attribute", () => { describe("Attribute", () => {
describe("#constructor()", () => { describe("#constructor()", () => {

View File

@ -1,6 +1,6 @@
import { XmlAttributeComponent } from "./default-attributes"; import { XmlAttributeComponent } from "./default-attributes";
interface IAttributesProperties { export interface IAttributesProperties {
val?: string | number | boolean; val?: string | number | boolean;
color?: string; color?: string;
space?: string; space?: string;

View File

@ -1,3 +1,5 @@
import { IXmlableObject } from "./xmlable-object";
export abstract class BaseXmlComponent { export abstract class BaseXmlComponent {
protected rootKey: string; protected rootKey: string;
@ -5,5 +7,5 @@ export abstract class BaseXmlComponent {
this.rootKey = rootKey; this.rootKey = rootKey;
} }
public abstract prepForXml(): object; public abstract prepForXml(): IXmlableObject;
} }

View File

@ -1,6 +1,7 @@
import { BaseXmlComponent } from "./base"; import { BaseXmlComponent } from "./base";
import { IXmlableObject } from "./xmlable-object";
type AttributeMap<T> = {[P in keyof T]: string}; export type AttributeMap<T> = {[P in keyof T]: string};
export abstract class XmlAttributeComponent<T> extends BaseXmlComponent { export abstract class XmlAttributeComponent<T> extends BaseXmlComponent {
protected root: T; protected root: T;
@ -11,7 +12,7 @@ export abstract class XmlAttributeComponent<T> extends BaseXmlComponent {
this.root = properties; this.root = properties;
} }
public prepForXml(): {_attr: {[key: string]: (string | number | boolean)}} { public prepForXml(): IXmlableObject {
const attrs = {}; const attrs = {};
Object.keys(this.root).forEach((key) => { Object.keys(this.root).forEach((key) => {
const value = this.root[key]; const value = this.root[key];

View File

@ -1,4 +1,5 @@
import { BaseXmlComponent } from "./base"; import { BaseXmlComponent } from "./base";
import { IXmlableObject } from "./xmlable-object";
export { BaseXmlComponent }; export { BaseXmlComponent };
export abstract class XmlComponent extends BaseXmlComponent { export abstract class XmlComponent extends BaseXmlComponent {
@ -9,7 +10,7 @@ export abstract class XmlComponent extends BaseXmlComponent {
this.root = new Array<BaseXmlComponent>(); this.root = new Array<BaseXmlComponent>();
} }
public prepForXml(): object { public prepForXml(): IXmlableObject {
const children = this.root.map((comp) => { const children = this.root.map((comp) => {
if (comp instanceof BaseXmlComponent) { if (comp instanceof BaseXmlComponent) {
return comp.prepForXml(); return comp.prepForXml();
@ -22,5 +23,5 @@ export abstract class XmlComponent extends BaseXmlComponent {
} }
} }
export * from "./attributes" export * from "./attributes";
export * from "./default-attributes"; export * from "./default-attributes";

View File

@ -1,6 +1,7 @@
import { assert } from "chai"; import { assert } from "chai";
import { XmlComponent } from "../../../docx/xml-components";
import { Utility } from "../../utility"; import { Utility } from "../../tests/utility";
import { XmlComponent } from "./";
class TestComponent extends XmlComponent { class TestComponent extends XmlComponent {

View File

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

View File

@ -1,10 +1,10 @@
import { assert } from "chai"; import { assert } from "chai";
import * as docx from "../../docx"; import * as docx from "../docx";
import { Attributes } from "../../docx/xml-components"; import { Attributes } from "../docx/xml-components";
import { Formatter } from "../../export/formatter"; import { Formatter } from "../export/formatter";
import { Properties } from "../../properties"; import { Properties } from "../properties";
import { Utility } from "../utility"; import { Utility } from "../tests/utility";
describe("Formatter", () => { describe("Formatter", () => {
let formatter: Formatter; let formatter: Formatter;
@ -40,6 +40,10 @@ describe("Formatter", () => {
}); });
let newJson = formatter.format(attributes); let newJson = formatter.format(attributes);
newJson = Utility.jsonify(newJson); newJson = Utility.jsonify(newJson);
if (newJson._attr === undefined) {
assert.fail();
return;
}
assert.isDefined(newJson._attr["w:rsidSect"]); assert.isDefined(newJson._attr["w:rsidSect"]);
}); });
@ -49,6 +53,10 @@ describe("Formatter", () => {
}); });
let newJson = formatter.format(attributes); let newJson = formatter.format(attributes);
newJson = Utility.jsonify(newJson); newJson = Utility.jsonify(newJson);
if (newJson._attr === undefined) {
assert.fail();
return;
}
assert.isDefined(newJson._attr["w:val"]); assert.isDefined(newJson._attr["w:val"]);
}); });

View File

@ -1,7 +1,8 @@
import { BaseXmlComponent } from "../docx/xml-components"; import { BaseXmlComponent } from "../docx/xml-components";
import { IXmlableObject } from "../docx/xml-components/xmlable-object";
export class Formatter { export class Formatter {
public format(input: BaseXmlComponent): any { public format(input: BaseXmlComponent): IXmlableObject {
return input.prepForXml(); return input.prepForXml();
} }
} }

View File

@ -20,6 +20,6 @@ export class ExpressPacker extends Packer {
public pack(name: string): void { public pack(name: string): void {
this.res.attachment(`${name}.docx`); this.res.attachment(`${name}.docx`);
super.pack(this.res); super.compile(this.res);
} }
} }

View File

@ -16,6 +16,6 @@ export class LocalPacker extends Packer {
public pack(path: string): void { public pack(path: string): void {
path = path.replace(/.docx$/, ""); path = path.replace(/.docx$/, "");
this.stream = fs.createWriteStream(`${path}.docx`); this.stream = fs.createWriteStream(`${path}.docx`);
super.pack(this.stream); super.compile(this.stream);
} }
} }

View File

@ -1,4 +1,6 @@
import * as archiver from "archiver"; import * as archiver from "archiver";
import * as express from "express";
import * as fs from "fs";
import * as path from "path"; import * as path from "path";
import * as xml from "xml"; import * as xml from "xml";
import { Document } from "../../docx"; import { Document } from "../../docx";
@ -12,7 +14,7 @@ import { Formatter } from "../formatter";
const TEMPLATE_PATH = path.resolve(__dirname, "../../../template"); const TEMPLATE_PATH = path.resolve(__dirname, "../../../template");
export abstract class Packer { export abstract class Packer {
protected archive: any; protected archive: archiver.Archiver;
private formatter: Formatter; private formatter: Formatter;
private style: Styles; private style: Styles;
@ -42,15 +44,13 @@ export abstract class Packer {
}); });
} }
public pack(output: any): void { protected compile(output: fs.WriteStream | express.Response): void {
this.archive.pipe(output); this.archive.pipe(output);
this.archive.glob("**", { this.archive.glob("**", {
expand: true,
cwd: TEMPLATE_PATH, cwd: TEMPLATE_PATH,
}); });
this.archive.glob("**/.rels", { this.archive.glob("**/.rels", {
expand: true,
cwd: TEMPLATE_PATH, cwd: TEMPLATE_PATH,
}); });

View File

@ -35,39 +35,39 @@ export class Numbering extends XmlComponent {
const abstractNumbering = this.createAbstractNumbering(); const abstractNumbering = this.createAbstractNumbering();
abstractNumbering.createLevel(0, "bullet", "•", "left") abstractNumbering.createLevel(0, "bullet", "•", "left")
.addParagraphProperty(new Indent(720, 360)) .addParagraphProperty(new Indent({ left: 720, hanging: 360 }))
.addRunProperty(new RunFonts("Symbol", "default")); .addRunProperty(new RunFonts("Symbol", "default"));
abstractNumbering.createLevel(1, "bullet", "o", "left") abstractNumbering.createLevel(1, "bullet", "o", "left")
.addParagraphProperty(new Indent(1440, 360)) .addParagraphProperty(new Indent({ left: 1440, hanging: 360 }))
.addRunProperty(new RunFonts("Courier New", "default")); .addRunProperty(new RunFonts("Courier New", "default"));
abstractNumbering.createLevel(2, "bullet", "•", "left") abstractNumbering.createLevel(2, "bullet", "•", "left")
.addParagraphProperty(new Indent(2160, 360)) .addParagraphProperty(new Indent({ left: 2160, hanging: 360 }))
.addRunProperty(new RunFonts("Wingdings", "default")); .addRunProperty(new RunFonts("Wingdings", "default"));
abstractNumbering.createLevel(3, "bullet", "•", "left") abstractNumbering.createLevel(3, "bullet", "•", "left")
.addParagraphProperty(new Indent(2880, 360)) .addParagraphProperty(new Indent({ left: 2880, hanging: 360 }))
.addRunProperty(new RunFonts("Symbol", "default")); .addRunProperty(new RunFonts("Symbol", "default"));
abstractNumbering.createLevel(4, "bullet", "o", "left") abstractNumbering.createLevel(4, "bullet", "o", "left")
.addParagraphProperty(new Indent(3600, 360)) .addParagraphProperty(new Indent({ left: 3600, hanging: 360 }))
.addRunProperty(new RunFonts("Courier New", "default")); .addRunProperty(new RunFonts("Courier New", "default"));
abstractNumbering.createLevel(5, "bullet", "•", "left") abstractNumbering.createLevel(5, "bullet", "•", "left")
.addParagraphProperty(new Indent(4320, 360)) .addParagraphProperty(new Indent({ left: 4320, hanging: 360 }))
.addRunProperty(new RunFonts("Wingdings", "default")); .addRunProperty(new RunFonts("Wingdings", "default"));
abstractNumbering.createLevel(6, "bullet", "•", "left") abstractNumbering.createLevel(6, "bullet", "•", "left")
.addParagraphProperty(new Indent(5040, 360)) .addParagraphProperty(new Indent({ left: 5040, hanging: 360 }))
.addRunProperty(new RunFonts("Symbol", "default")); .addRunProperty(new RunFonts("Symbol", "default"));
abstractNumbering.createLevel(7, "bullet", "o", "left") abstractNumbering.createLevel(7, "bullet", "o", "left")
.addParagraphProperty(new Indent(5760, 360)) .addParagraphProperty(new Indent({ left: 5760, hanging: 360 }))
.addRunProperty(new RunFonts("Courier New", "default")); .addRunProperty(new RunFonts("Courier New", "default"));
abstractNumbering.createLevel(8, "bullet", "•", "left") abstractNumbering.createLevel(8, "bullet", "•", "left")
.addParagraphProperty(new Indent(6480, 360)) .addParagraphProperty(new Indent({ left: 6480, hanging: 360 }))
.addRunProperty(new RunFonts("Wingdings", "default")); .addRunProperty(new RunFonts("Wingdings", "default"));
this.createConcreteNumbering(abstractNumbering); this.createConcreteNumbering(abstractNumbering);

View File

@ -56,7 +56,7 @@ class LevelJc extends XmlComponent {
} }
} }
class LevelBase extends XmlComponent { export class LevelBase extends XmlComponent {
private paragraphProperties: ParagraphProperties; private paragraphProperties: ParagraphProperties;
private runProperties: RunProperties; private runProperties: RunProperties;
@ -196,15 +196,25 @@ class LevelBase extends XmlComponent {
return this; return this;
} }
public indent(left: number, hanging?: number): Level { public indent(attrs: object): Level {
this.addParagraphProperty(new paragraph.Indent(left, hanging)); this.addParagraphProperty(new paragraph.Indent(attrs));
return this; return this;
} }
public spacing(params: paragraph.ISpacingProperties): Level { public spacing(params: paragraph.ISpacingProperties): Level {
this.addParagraphProperty(new paragraph.Spacing(params)); this.addParagraphProperty(new paragraph.Spacing(params));
return this; return this;
}; }
public keepNext(): Level {
this.addParagraphProperty(new paragraph.KeepNext());
return this;
}
public keepLines(): Level {
this.addParagraphProperty(new paragraph.KeepLines());
return this;
}
} }
export class Level extends LevelBase { export class Level extends LevelBase {

View File

@ -42,7 +42,7 @@ class LevelOverrideAttributes extends XmlAttributeComponent<{ilvl: number}> {
protected xmlKeys = {ilvl: "w:ilvl"}; protected xmlKeys = {ilvl: "w:ilvl"};
} }
class LevelOverride extends XmlComponent { export class LevelOverride extends XmlComponent {
private levelNum: number; private levelNum: number;
private lvl?: LevelForOverride; private lvl?: LevelForOverride;

View File

@ -1,9 +1,9 @@
import { expect } from "chai"; import { expect } from "chai";
import { Formatter } from "../export/formatter"; import { Formatter } from "../export/formatter";
import { Numbering } from "../numbering"; import { Numbering } from "./";
import { AbstractNumbering } from "../numbering/abstract-numbering"; import { AbstractNumbering } from "./abstract-numbering";
import { LevelForOverride } from "../numbering/level"; import { LevelForOverride } from "./level";
import { Num } from "../numbering/num"; import { Num } from "./num";
describe("Numbering", () => { describe("Numbering", () => {
@ -111,7 +111,7 @@ describe("AbstractNumbering", () => {
it("#indent", () => { it("#indent", () => {
const abstractNumbering = new AbstractNumbering(1); const abstractNumbering = new AbstractNumbering(1);
const level = abstractNumbering.createLevel(0, "lowerLetter", "%0.") const level = abstractNumbering.createLevel(0, "lowerLetter", "%0.")
.indent(720); .indent({ left: 720 });
const tree = new Formatter().format(level); const tree = new Formatter().format(level);
expect(tree["w:lvl"]).to.include({ expect(tree["w:lvl"]).to.include({
"w:pPr": [{"w:ind": [{_attr: {"w:left": 720}}]}], "w:pPr": [{"w:ind": [{_attr: {"w:left": 720}}]}],
@ -222,6 +222,26 @@ describe("AbstractNumbering", () => {
], ],
}); });
}); });
it("#keepLines", () => {
const abstractNumbering = new AbstractNumbering(1);
const level = abstractNumbering.createLevel(0, "lowerRoman", "%0.")
.keepLines();
const tree = new Formatter().format(level);
expect(tree["w:lvl"]).to.include({
"w:pPr": [{"w:keepLines": []}],
});
});
it("#keepNext", () => {
const abstractNumbering = new AbstractNumbering(1);
const level = abstractNumbering.createLevel(0, "lowerRoman", "%0.")
.keepNext();
const tree = new Formatter().format(level);
expect(tree["w:lvl"]).to.include({
"w:pPr": [{"w:keepNext": []}],
});
});
}); });
describe("formatting methods: run properties", () => { describe("formatting methods: run properties", () => {

View File

@ -57,7 +57,7 @@ export class Revision extends XmlComponent {
} }
} }
abstract class DateComponent extends XmlComponent { export abstract class DateComponent extends XmlComponent {
protected getCurrentDate(): string { protected getCurrentDate(): string {
const date = new Date(); const date = new Date();
const year = date.getFullYear(); const year = date.getFullYear();

View File

@ -2,7 +2,7 @@ import { DocumentAttributes } from "../docx/document/document-attributes";
import { XmlComponent } from "../docx/xml-components"; import { XmlComponent } from "../docx/xml-components";
import { Created, Creator, Description, Keywords, LastModifiedBy, Modified, Revision, Subject, Title } from "./components"; import { Created, Creator, Description, Keywords, LastModifiedBy, Modified, Revision, Subject, Title } from "./components";
interface IPropertiesOptions { export interface IPropertiesOptions {
title?: string; title?: string;
subject?: string; subject?: string;
creator?: string; creator?: string;

View File

@ -1,7 +1,7 @@
import { expect } from "chai"; import { expect } from "chai";
import { Formatter } from "../export/formatter"; import { Formatter } from "../export/formatter";
import { Properties } from "../properties"; import { Properties } from "./";
describe("Properties", () => { describe("Properties", () => {

View File

@ -1,6 +1,6 @@
import { XmlAttributeComponent } from "../docx/xml-components"; import { XmlAttributeComponent } from "../docx/xml-components";
interface IRelationshipsAttributesProperties { export interface IRelationshipsAttributesProperties {
xmlns: string; xmlns: string;
} }

View File

@ -1,10 +1,24 @@
import { Size } from "../../docx/run/formatting";
import { RunProperties } from "../../docx/run/properties"; import { RunProperties } from "../../docx/run/properties";
import { RunFonts } from "../../docx/run/run-fonts";
import { XmlComponent } from "../../docx/xml-components"; import { XmlComponent } from "../../docx/xml-components";
export class RunPropertiesDefaults extends XmlComponent { export class RunPropertiesDefaults extends XmlComponent {
private properties: RunProperties;
constructor() { constructor() {
super("w:rPrDefault"); super("w:rPrDefault");
this.root.push(new RunProperties()); this.properties = new RunProperties();
this.root.push(this.properties);
}
public size(size: number): RunPropertiesDefaults {
this.properties.push(new Size(size));
return this;
}
public font(fontName: string): RunPropertiesDefaults {
this.properties.push(new RunFonts(fontName));
return this;
} }
} }

View File

@ -1,7 +1,7 @@
import { Color, Italics, Size } from "../docx/run/formatting"; import { Color, Italics, Size } from "../docx/run/formatting";
import { Styles } from "./"; import { Styles } from "./";
import { DocumentDefaults } from "./defaults"; // import { DocumentDefaults } from "./defaults";
import { import {
Heading1Style, Heading2Style, Heading3Style, Heading4Style, Heading5Style, Heading6Style, Heading1Style, Heading2Style, Heading3Style, Heading4Style, Heading5Style, Heading6Style,
ListParagraph, TitleStyle, ListParagraph, TitleStyle,
@ -11,7 +11,7 @@ export class DefaultStylesFactory {
public newInstance(): Styles { public newInstance(): Styles {
const styles = new Styles(); const styles = new Styles();
styles.push(new DocumentDefaults()); styles.createDocumentDefaults();
const titleStyle = new TitleStyle(); const titleStyle = new TitleStyle();
titleStyle.addRunProperty(new Size(56)); titleStyle.addRunProperty(new Size(56));

View File

@ -1,5 +1,6 @@
import { DocumentAttributes } from "../docx/document/document-attributes"; import { DocumentAttributes } from "../docx/document/document-attributes";
import { XmlComponent } from "../docx/xml-components"; import { XmlComponent } from "../docx/xml-components";
import { DocumentDefaults } from "./defaults";
import { ParagraphStyle } from "./style"; import { ParagraphStyle } from "./style";
export class Styles extends XmlComponent { export class Styles extends XmlComponent {
@ -14,11 +15,7 @@ export class Styles extends XmlComponent {
w15: "http://schemas.microsoft.com/office/word/2012/wordml", w15: "http://schemas.microsoft.com/office/word/2012/wordml",
Ignorable: "w14 w15", Ignorable: "w14 w15",
})); }));
// let latentStyles = new LatentStyles();
// latentStyles.push(new LatentStyleException(new LatentStyleExceptionAttributes({
// name: "Normal"
// })));
// this.root.push(latentStyles);
} }
public push(style: XmlComponent): Styles { public push(style: XmlComponent): Styles {
@ -26,6 +23,12 @@ export class Styles extends XmlComponent {
return this; return this;
} }
public createDocumentDefaults(): DocumentDefaults {
const defaults = new DocumentDefaults();
this.push(defaults);
return defaults;
}
public createParagraphStyle(styleId: string, name?: string): ParagraphStyle { public createParagraphStyle(styleId: string, name?: string): ParagraphStyle {
const para = new ParagraphStyle(styleId, name); const para = new ParagraphStyle(styleId, name);
this.push(para); this.push(para);

View File

@ -1,6 +1,6 @@
import { XmlAttributeComponent, XmlComponent } from "../../docx/xml-components"; import { XmlAttributeComponent, XmlComponent } from "../../docx/xml-components";
interface ILatentStyleExceptionAttributesProperties { export interface ILatentStyleExceptionAttributesProperties {
name?: string; name?: string;
uiPriority?: string; uiPriority?: string;
qFormat?: string; qFormat?: string;
@ -8,7 +8,7 @@ interface ILatentStyleExceptionAttributesProperties {
unhideWhenUsed?: string; unhideWhenUsed?: string;
} }
class LatentStyleExceptionAttributes extends XmlAttributeComponent<ILatentStyleExceptionAttributesProperties> { export class LatentStyleExceptionAttributes extends XmlAttributeComponent<ILatentStyleExceptionAttributesProperties> {
protected xmlKeys = { protected xmlKeys = {
name: "w:name", name: "w:name",
uiPriority: "w:uiPriority", uiPriority: "w:uiPriority",

View File

@ -171,15 +171,25 @@ export class ParagraphStyle extends Style {
return this; return this;
} }
public indent(left: number, hanging?: number): ParagraphStyle { public indent(attrs: object): ParagraphStyle {
this.addParagraphProperty(new paragraph.Indent(left, hanging)); this.addParagraphProperty(new paragraph.Indent(attrs));
return this; return this;
} }
public spacing(params: paragraph.ISpacingProperties): ParagraphStyle { public spacing(params: paragraph.ISpacingProperties): ParagraphStyle {
this.addParagraphProperty(new paragraph.Spacing(params)); this.addParagraphProperty(new paragraph.Spacing(params));
return this; return this;
}; }
public keepNext(): ParagraphStyle {
this.addParagraphProperty(new paragraph.KeepNext());
return this;
}
public keepLines(): ParagraphStyle {
this.addParagraphProperty(new paragraph.KeepLines());
return this;
}
} }
export class HeadingStyle extends ParagraphStyle { export class HeadingStyle extends ParagraphStyle {

View File

@ -1,8 +1,8 @@
import { assert, expect } from "chai"; import { assert, expect } from "chai";
import { Formatter } from "../export/formatter"; import { Formatter } from "../export/formatter";
import { Styles } from "../styles"; import { Styles } from "./";
import { ParagraphStyle, Style } from "../styles/style"; import { ParagraphStyle, Style } from "./style";
import * as components from "../styles/style/components"; import * as components from "./style/components";
describe("Styles", () => { describe("Styles", () => {
let styles: Styles; let styles: Styles;
@ -185,7 +185,7 @@ describe("ParagraphStyle", () => {
describe("formatting methods: paragraph properties", () => { describe("formatting methods: paragraph properties", () => {
it("#indent", () => { it("#indent", () => {
const style = new ParagraphStyle("myStyleId") const style = new ParagraphStyle("myStyleId")
.indent(720); .indent({ left: 720 });
const tree = new Formatter().format(style); const tree = new Formatter().format(style);
expect(tree).to.deep.equal({ expect(tree).to.deep.equal({
"w:style": [ "w:style": [
@ -326,6 +326,32 @@ describe("ParagraphStyle", () => {
], ],
}); });
}); });
it("#keepLines", () => {
const style = new ParagraphStyle("myStyleId")
.keepLines();
const tree = new Formatter().format(style);
expect(tree).to.deep.equal({
"w:style": [
{_attr: {"w:type": "paragraph", "w:styleId": "myStyleId"}},
{"w:pPr": [{"w:keepLines": []}]},
{"w:rPr": []},
],
});
});
it("#keepNext", () => {
const style = new ParagraphStyle("myStyleId")
.keepNext();
const tree = new Formatter().format(style);
expect(tree).to.deep.equal({
"w:style": [
{_attr: {"w:type": "paragraph", "w:styleId": "myStyleId"}},
{"w:pPr": [{"w:keepNext": []}]},
{"w:rPr": []},
],
});
});
}); });
describe("formatting methods: run properties", () => { describe("formatting methods: run properties", () => {

View File

@ -9,5 +9,9 @@
"sourceRoot": "./", "sourceRoot": "./",
"rootDir": "./", "rootDir": "./",
"module": "commonjs" "module": "commonjs"
} },
"include": [
"**/*.spec.ts",
"**/*.d.ts"
]
} }

View File

@ -1,5 +1,6 @@
/* tslint:disable */ /* tslint:disable */
import { assert } from "chai"; import { assert } from "chai";
import { Utility } from "./utility"; import { Utility } from "./utility";
/* tslint:enable */ /* tslint:enable */

View File

@ -1,16 +0,0 @@
import { assert } from "chai";
import { TextRun } from "../../../docx/run/text-run";
import { Utility } from "../../utility";
describe("TextRun", () => {
let run: TextRun;
describe("#constructor()", () => {
it("should add text into run", () => {
run = new TextRun("test");
const newJson = Utility.jsonify(run);
assert.equal(newJson.root[1].root, "test");
});
});
});

View File

@ -8,9 +8,12 @@
"outDir": "../build", "outDir": "../build",
"sourceRoot": "./", "sourceRoot": "./",
"rootDir": "./", "rootDir": "./",
"module": "commonjs" "module": "commonjs",
"declaration": true
}, },
"exclude": [ "exclude": [
"tests" "tests",
"**/*.spec.ts",
"**/_*"
] ]
} }