Compare commits

...

62 Commits
2.0.0 ... 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
a706455a7c Merge pull request #30 from felipeochoa/overrides
Add support for numbering level overrides
2017-04-12 18:34:07 +01:00
8c388a95c4 bump patch version 2017-04-12 16:01:26 +02:00
9a41d78ecb add an additional demo 2017-04-12 16:00:16 +02:00
6fc4ad782a add #overrideLevel method to concrete numberings 2017-04-12 16:00:16 +02:00
16b9057ac6 prepare Level to be extended for overrides 2017-04-12 15:57:26 +02:00
78 changed files with 755 additions and 194 deletions

View File

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

View File

@ -1,10 +1,16 @@
language: node_js
node_js:
- "6"
- "node"
- "stable"
install:
- npm install
script:
- npm run lint
- npm test
after_failure:
- "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
```
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
Please refer to [the Wiki](https://github.com/dolanmiu/docx/wiki) for details on how to use this library, examples and much more!
Full documentation can be found here: [http://dolanmiu.github.io/docx](http://dolanmiu.github.io/docx)
## Simple Usage
```js

74
demo/demo2.js Normal file
View File

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

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",
"version": "2.0.0",
"version": "3.0.0",
"description": "Generate .docx documents with JavaScript (formerly Office-Clippy)",
"main": "build/index.js",
"scripts": {
@ -9,7 +9,8 @@
"prepublishOnly": "npm run build",
"lint": "tslint --project ./ts",
"build": "rimraf ./build && tsc -p ts",
"demo": "npm run build && node ./demo/demo.js"
"demo": "npm run build && node ./demo",
"typedoc": "typedoc --out docs/ ts/ --module commonjs --target ES6 --disableOutputCheck"
},
"files": [
"ts",
@ -31,8 +32,9 @@
"officegen",
"clippy"
],
"types": "./build/index.d.ts",
"dependencies": {
"@types/archiver": "^0.15.37",
"@types/archiver": "^1.3.4",
"@types/express": "^4.0.35",
"archiver": "^1.3.0",
"xml": "^1.0.1"
@ -48,8 +50,11 @@
"@types/mocha": "^2.2.39",
"chai": "^3.5.0",
"mocha": "^3.2.0",
"prompt": "^1.0.0",
"rimraf": "^2.5.2",
"tslint": "^4.5.1",
"typescript": "^2.2.1"
"shelljs": "^0.7.7",
"tslint": "^5.1.0",
"typedoc": "^0.5.10",
"typescript": "2.4.1"
}
}

View File

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

View File

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

View File

@ -1,6 +1,7 @@
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", () => {
let document: docx.Document;
@ -41,7 +42,7 @@ describe("Document", () => {
expect(body[0]).to.have.property("w:p").which.includes({
"w:r": [
{"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 { Paragraph } from "./paragraph";
export * from "./paragraph";
export { Run } from "./run";
export { TextRun } from "./run/text-run";
export { PictureRun } from "./run/picture-run";

View File

@ -1,14 +1,14 @@
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"};
}
export class Alignment extends XmlComponent {
constructor(type: alignmentOptions) {
constructor(type: AlignmentOptions) {
super("w:jc");
this.root.push(new AlignmentAttributes({val: type}));
}

View File

@ -1,6 +1,7 @@
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", () => {
// TODO: Need tests here

View File

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

View File

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

View File

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

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

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

View File

@ -1,6 +1,7 @@
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", () => {
let pageBreak: PageBreak;

View File

@ -1,7 +1,8 @@
import { assert, expect } from "chai";
import * as docx from "../../../docx";
import { Formatter } from "../../../export/formatter";
import { Numbering } from "../../../numbering";
import * as docx from "../../docx";
import { Formatter } from "../../export/formatter";
import { Numbering } from "../../numbering";
describe("Paragraph", () => {
let paragraph: docx.Paragraph;
@ -39,7 +40,7 @@ describe("Paragraph", () => {
expect(tree).to.be.an("array").which.includes({
"w:r": [
{"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);
expect(tree).to.deep.equal({
"w:p": [{
"w:pPr": [{
"w:pPr": [],
}, {
"w:r": [
{"w:rPr": []},
{"w:br": [{_attr: {"w:type": "page"}}]},
],
}],
}],
});
});
});
@ -240,7 +241,7 @@ describe("Paragraph", () => {
describe("#indent", () => {
it("should set the paragraph indent to the given values", () => {
paragraph.indent(720);
paragraph.indent({ left: 720 });
const tree = new Formatter().format(paragraph);
expect(tree).to.deep.equal({
"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 { Spacing } from "../../../docx/paragraph/spacing";
import { Formatter } from "../../../export/formatter";
import { Formatter } from "../../export/formatter";
import { Spacing } from "./spacing";
describe("Spacing", () => {
describe("#constructor", () => {

View File

@ -1,6 +1,7 @@
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", () => {
let style: Style;

View File

@ -1,6 +1,7 @@
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", () => {
let tabStop: LeftTabStop;

View File

@ -1,6 +1,6 @@
import { XmlAttributeComponent, XmlComponent } from "../xml-components";
class TabStop extends XmlComponent {
export class TabStop extends XmlComponent {
constructor(tab: Tab) {
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"};
}
class Tab extends XmlComponent {
export class Tab extends XmlComponent {
constructor(value: tabOptions, position: string | number) {
constructor(value: TabOptions, position: string | number) {
super("w:tab");
this.root.push(new TabAttributes({
val: value,

View File

@ -1,6 +1,7 @@
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", () => {
let numberProperties: NumberProperties;

View File

@ -1,6 +1,7 @@
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", () => {
let currentBreak: Break;

View File

@ -1,7 +1,8 @@
import { assert } from "chai";
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", () => {
let currentBreak: Drawing;
@ -20,7 +21,7 @@ describe("Drawing", () => {
it("should create a Drawing with correct root key", () => {
const newJson = Utility.jsonify(currentBreak);
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 { GraphicData } from "./graphic-data";
interface IGraphicProperties {
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 {
constructor(text: string) {
super("w:t");
this.root.push(new TextAttributes({space: "preserve"}));
if (text) {
this.root.push(text);
}

View File

@ -1,6 +1,7 @@
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", () => {

View File

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

View File

@ -1,6 +1,7 @@
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", () => {
let subScript: SubScript;

View File

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

View File

@ -1,6 +1,7 @@
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", () => {
let strike: Strike;

View File

@ -1,6 +1,7 @@
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", () => {
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 * as u from "../../../docx/run/underline";
import { Formatter } from "../../../export/formatter";
import { Utility } from "../../utility";
import { Formatter } from "../../export/formatter";
import { Utility } from "../../tests/utility";
import * as u from "./underline";
describe("Underline", () => {

View File

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

View File

@ -1,6 +1,7 @@
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("#constructor", () => {

View File

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

View File

@ -1,6 +1,7 @@
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("#constructor", () => {

View File

@ -1,13 +1,13 @@
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 {
constructor() {
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));
return this;
}
@ -19,7 +19,7 @@ export class TableProperties extends XmlComponent {
}
interface ITableWidth {
type: widthTypes;
type: WidthTypes;
w: number | string;
}
@ -28,20 +28,20 @@ class TableWidthAttributes extends XmlAttributeComponent<ITableWidth> {
}
class PreferredTableWidth extends XmlComponent {
constructor(type: widthTypes, w: number | string) {
constructor(type: WidthTypes, w: number | string) {
super("w:tblW");
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"};
}
class TableLayout extends XmlComponent {
constructor(type: tableLayout) {
constructor(type: TableLayoutOptions) {
super("w:tblLayout");
this.root.push(new TableLayoutAttributes({type}));
}

View File

@ -1,7 +1,9 @@
/* tslint:disable:no-unused-expression */
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("#constructor", () => {
@ -36,7 +38,7 @@ describe("Table", () => {
{"w:tcPr": []},
{"w:p": [
{"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({
@ -65,7 +67,7 @@ describe("Table", () => {
{"w:tcPr": []},
{"w:p": [
{"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({
@ -153,7 +155,7 @@ describe("Table", () => {
{"w:tcPr": []},
{"w:p": [
{"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:p": [
{"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 { Attributes } from "../../../docx/xml-components";
import { Attributes } from "./";
describe("Attribute", () => {
describe("#constructor()", () => {

View File

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

View File

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

View File

@ -1,6 +1,7 @@
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 {
protected root: T;
@ -11,7 +12,7 @@ export abstract class XmlAttributeComponent<T> extends BaseXmlComponent {
this.root = properties;
}
public prepForXml(): {_attr: {[key: string]: (string | number | boolean)}} {
public prepForXml(): IXmlableObject {
const attrs = {};
Object.keys(this.root).forEach((key) => {
const value = this.root[key];

View File

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

View File

@ -1,6 +1,7 @@
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 {

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

View File

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

View File

@ -20,6 +20,6 @@ export class ExpressPacker extends Packer {
public pack(name: string): void {
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 {
path = path.replace(/.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 express from "express";
import * as fs from "fs";
import * as path from "path";
import * as xml from "xml";
import { Document } from "../../docx";
@ -12,7 +14,7 @@ import { Formatter } from "../formatter";
const TEMPLATE_PATH = path.resolve(__dirname, "../../../template");
export abstract class Packer {
protected archive: any;
protected archive: archiver.Archiver;
private formatter: Formatter;
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.glob("**", {
expand: true,
cwd: TEMPLATE_PATH,
});
this.archive.glob("**/.rels", {
expand: true,
cwd: TEMPLATE_PATH,
});

View File

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

View File

@ -56,21 +56,29 @@ class LevelJc extends XmlComponent {
}
}
export class Level extends XmlComponent {
export class LevelBase extends XmlComponent {
private paragraphProperties: ParagraphProperties;
private runProperties: RunProperties;
constructor(level: number, numberFormat: string, levelText: string, lvlJc: string) {
constructor(level: number, start?: number, numberFormat?: string, levelText?: string, lvlJc?: string) {
super("w:lvl");
this.root.push(new LevelAttributes({
ilvl: level,
tentative: 1,
}));
this.root.push(new Start(1));
if (start !== undefined) {
this.root.push(new Start(start));
}
if (numberFormat !== undefined) {
this.root.push(new NumberFormat(numberFormat));
}
if (levelText !== undefined) {
this.root.push(new LevelText(levelText));
}
if (lvlJc !== undefined) {
this.root.push(new LevelJc(lvlJc));
}
this.paragraphProperties = new ParagraphProperties();
this.runProperties = new RunProperties();
@ -188,13 +196,33 @@ export class Level extends XmlComponent {
return this;
}
public indent(left: number, hanging?: number): Level {
this.addParagraphProperty(new paragraph.Indent(left, hanging));
public indent(attrs: object): Level {
this.addParagraphProperty(new paragraph.Indent(attrs));
return this;
}
public spacing(params: paragraph.ISpacingProperties): Level {
this.addParagraphProperty(new paragraph.Spacing(params));
return this;
};
}
public keepNext(): Level {
this.addParagraphProperty(new paragraph.KeepNext());
return this;
}
public keepLines(): Level {
this.addParagraphProperty(new paragraph.KeepLines());
return this;
}
}
export class Level extends LevelBase {
// This is the level that sits under abstractNum. We make a
// handful of properties required
constructor(level: number, numberFormat: string, levelText: string, lvlJc: string) {
super(level, 1, numberFormat, levelText, lvlJc);
}
}
export class LevelForOverride extends LevelBase {}

View File

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

View File

@ -1,8 +1,9 @@
import { expect } from "chai";
import { Formatter } from "../export/formatter";
import { Numbering } from "../numbering";
import { AbstractNumbering } from "../numbering/abstract-numbering";
import { Num } from "../numbering/num";
import { Numbering } from "./";
import { AbstractNumbering } from "./abstract-numbering";
import { LevelForOverride } from "./level";
import { Num } from "./num";
describe("Numbering", () => {
@ -110,7 +111,7 @@ describe("AbstractNumbering", () => {
it("#indent", () => {
const abstractNumbering = new AbstractNumbering(1);
const level = abstractNumbering.createLevel(0, "lowerLetter", "%0.")
.indent(720);
.indent({ left: 720 });
const tree = new Formatter().format(level);
expect(tree["w:lvl"]).to.include({
"w:pPr": [{"w:ind": [{_attr: {"w:left": 720}}]}],
@ -221,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", () => {
@ -394,3 +415,50 @@ describe("AbstractNumbering", () => {
});
});
});
describe("concrete numbering", () => {
describe("#overrideLevel", () => {
let numbering;
let abstractNumbering;
let concreteNumbering;
beforeEach(() => {
numbering = new Numbering();
abstractNumbering = numbering.createAbstractNumbering();
concreteNumbering = numbering.createConcreteNumbering(abstractNumbering);
});
it("sets a new override level for the given level number", () => {
concreteNumbering.overrideLevel(3);
const tree = new Formatter().format(concreteNumbering);
expect(tree["w:num"]).to.include({"w:lvlOverride": [{_attr: {"w:ilvl": 3}}]});
});
it("sets the startOverride element if start is given", () => {
concreteNumbering.overrideLevel(1, 9);
const tree = new Formatter().format(concreteNumbering);
expect(tree["w:num"]).to.include({
"w:lvlOverride": [
{_attr: {"w:ilvl": 1}},
{"w:startOverride": [{_attr: {"w:val": 9}}]},
],
});
});
it("sets the lvl element if overrideLevel.level is accessed", () => {
const ol = concreteNumbering.overrideLevel(1);
expect(ol.level).to.be.instanceof(LevelForOverride);
const tree = new Formatter().format(concreteNumbering);
expect(tree["w:num"]).to.include({
"w:lvlOverride": [
{_attr: {"w:ilvl": 1}},
{"w:lvl": [
{_attr: {"w15:tentative": 1, "w:ilvl": 1}},
{"w:pPr": []},
{"w:rPr": []},
]},
],
});
});
});
});

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 {
const date = new Date();
const year = date.getFullYear();

View File

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

View File

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

View File

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

View File

@ -1,10 +1,24 @@
import { Size } from "../../docx/run/formatting";
import { RunProperties } from "../../docx/run/properties";
import { RunFonts } from "../../docx/run/run-fonts";
import { XmlComponent } from "../../docx/xml-components";
export class RunPropertiesDefaults extends XmlComponent {
private properties: RunProperties;
constructor() {
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 { Styles } from "./";
import { DocumentDefaults } from "./defaults";
// import { DocumentDefaults } from "./defaults";
import {
Heading1Style, Heading2Style, Heading3Style, Heading4Style, Heading5Style, Heading6Style,
ListParagraph, TitleStyle,
@ -11,7 +11,7 @@ export class DefaultStylesFactory {
public newInstance(): Styles {
const styles = new Styles();
styles.push(new DocumentDefaults());
styles.createDocumentDefaults();
const titleStyle = new TitleStyle();
titleStyle.addRunProperty(new Size(56));

View File

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

View File

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

View File

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

View File

@ -1,8 +1,8 @@
import { assert, expect } from "chai";
import { Formatter } from "../export/formatter";
import { Styles } from "../styles";
import { ParagraphStyle, Style } from "../styles/style";
import * as components from "../styles/style/components";
import { Styles } from "./";
import { ParagraphStyle, Style } from "./style";
import * as components from "./style/components";
describe("Styles", () => {
let styles: Styles;
@ -185,7 +185,7 @@ describe("ParagraphStyle", () => {
describe("formatting methods: paragraph properties", () => {
it("#indent", () => {
const style = new ParagraphStyle("myStyleId")
.indent(720);
.indent({ left: 720 });
const tree = new Formatter().format(style);
expect(tree).to.deep.equal({
"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", () => {

View File

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

View File

@ -1,5 +1,6 @@
/* tslint:disable */
import { assert } from "chai";
import { Utility } from "./utility";
/* 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",
"sourceRoot": "./",
"rootDir": "./",
"module": "commonjs"
"module": "commonjs",
"declaration": true
},
"exclude": [
"tests"
"tests",
"**/*.spec.ts",
"**/_*"
]
}