Merge branch 'master' into importDotx

# Conflicts:
#	src/import-dotx/import-dotx.ts
This commit is contained in:
Dolan
2018-10-31 22:09:36 +00:00
92 changed files with 857 additions and 404 deletions

3
.gitignore vendored
View File

@ -60,3 +60,6 @@ My Document.docx
# Temporary folder
tmp
# nyc
.nyc_output

25
.nycrc Normal file
View File

@ -0,0 +1,25 @@
{
"check-coverage": true,
"lines": 84.56,
"functions": 77.50,
"branches": 71.40,
"statements": 84.30,
"include": [
"src/**/*.ts"
],
"exclude": [
"src/**/*.spec.ts"
],
"reporter": [
"lcov",
"text",
"json"
],
"extension": [
".ts"
],
"cache": true,
"all": true,
"instrument": false,
"sourceMap": true
}

View File

@ -3,9 +3,10 @@ node_js:
- 9
install:
- npm install
- npm install -g codecov
script:
- npm run lint
- npm test
- npm run test.coverage
- npm run style
- npm run build
- npm run ts-node -- ./demo/demo1.ts
@ -32,12 +33,23 @@ script:
- npm run ts-node -- ./demo/demo22.ts
- npm run ts-node -- ./demo/demo23.ts
- npm run ts-node -- ./demo/demo24.ts
# - npm run ts-node -- ./demo/demo25.ts
- npm run ts-node -- ./demo/demo26.ts
- npm run ts-node -- ./demo/demo27.ts
- npm run ts-node -- ./demo/demo28.ts
- npm run ts-node -- ./demo/demo29.ts
- npm run ts-node -- ./demo/demo30.ts
- npm run ts-node -- ./demo/demo31.ts
- npm run ts-node -- ./demo/demo32.ts
- npm run ts-node -- ./demo/demo33.ts
- npm run ts-node -- ./demo/demo34.ts
after_failure:
- "cat /home/travis/builds/dolanmiu/docx/npm-debug.log"
after_success:
- npm run typedoc
- echo "docx.js.org" > docs/.nojekyll
- echo "docx.js.org" > docs/CNAME
- codecov
deploy:
provider: pages
skip-cleanup: true

View File

@ -15,6 +15,7 @@
[![Known Vulnerabilities][snky-image]][snky-url]
[![Chat on Gitter][gitter-image]][gitter-url]
[![PRs Welcome][pr-image]][pr-url]
[![codecov][codecov-image]][codecov-url]
<p align="center">
<img src="https://i.imgur.com/H5FA1Qy.gif" alt="drawing" width="800"/>
@ -81,3 +82,5 @@ Made with 💖
[gitter-url]: https://gitter.im/docx-lib/Lobby
[pr-image]: https://img.shields.io/badge/PRs-welcome-brightgreen.svg
[pr-url]: http://makeapullrequest.com
[codecov-image]: https://codecov.io/gh/dolanmiu/docx/branch/master/graph/badge.svg
[codecov-url]: https://codecov.io/gh/dolanmiu/docx

View File

@ -8,11 +8,11 @@ const doc = new Document();
const paragraph = new Paragraph("Hello World");
doc.addParagraph(paragraph);
const image = Media.addImage(doc, "./demo/images/image1.jpeg");
const image2 = Media.addImage(doc, "./demo/images/dog.png");
const image3 = Media.addImage(doc, "./demo/images/cat.jpg");
const image4 = Media.addImage(doc, "./demo/images/parrots.bmp");
const image5 = Media.addImage(doc, "./demo/images/pizza.gif");
const image = Media.addImage(doc, fs.readFileSync("./demo/images/image1.jpeg"));
const image2 = Media.addImage(doc, fs.readFileSync("./demo/images/dog.png"));
const image3 = Media.addImage(doc, fs.readFileSync("./demo/images/cat.jpg"));
const image4 = Media.addImage(doc, fs.readFileSync("./demo/images/parrots.bmp"));
const image5 = Media.addImage(doc, fs.readFileSync("./demo/images/pizza.gif"));
const imageBase64Data = `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`;
const image6 = Media.addImage(doc, Buffer.from(imageBase64Data, "base64"), 100, 100);

View File

@ -8,7 +8,7 @@ const doc = new Document();
const table = doc.createTable(4, 4);
table.getCell(2, 2).addContent(new Paragraph("Hello"));
const image = Media.addImage(doc, "./demo/images/image1.jpeg");
const image = Media.addImage(doc, fs.readFileSync("./demo/images/image1.jpeg"));
table.getCell(1, 1).addContent(image.Paragraph);
const packer = new Packer();

32
demo/demo34.ts Normal file
View File

@ -0,0 +1,32 @@
// Example of how you would create a table with float positions
// Import from 'docx' rather than '../build' if you install from npm
import * as fs from "fs";
import {
Document,
Packer,
Paragraph,
RelativeHorizontalPosition,
RelativeVerticalPosition,
TableAnchorType,
WidthType,
} from "../build";
const doc = new Document();
const table = doc.createTable(2, 2).float({
horizontalAnchor: TableAnchorType.MARGIN,
verticalAnchor: TableAnchorType.MARGIN,
relativeHorizontalPosition: RelativeHorizontalPosition.RIGHT,
relativeVerticalPosition: RelativeVerticalPosition.BOTTOM,
});
table.setFixedWidthLayout();
table.setWidth(WidthType.DXA, 4535);
table.getCell(0, 0).addContent(new Paragraph("Hello"));
table.getRow(0).mergeCells(0, 1);
const packer = new Packer();
packer.toBuffer(doc).then((buffer) => {
fs.writeFileSync("My Document.docx", buffer);
});

View File

@ -1,5 +1,15 @@
# Contribution Guidelines
* Include documentation reference(s) at the top of each file:
```js
// http://officeopenxml.com/WPdocument.php
```
* Follow Prettier standards, and consider using the [Prettier VSCode](https://marketplace.visualstudio.com/items?itemName=esbenp.prettier-vscode) plugin.
* Follow the `TSLint` rules
## Always think about the user
The number one pillar for contribution is to **ALWAYS** think about how the user will use the library.
@ -25,17 +35,33 @@ demo updated // Getting better, but capitalize the first letter
Unesesary coment removed // Make sure to use correct spelling
```
## Writing Code
## No leaky components in API interface
* Include documentation reference(s) at the top of each file:
This mainly applies to the API the end user will consume.
Try to make method parameters accept primatives, or `json` objects, so that child components are created **inside** the component, rather than being **injected** in.
This is so that:
1. Imports are much cleaner, no need for:
```js
// http://officeopenxml.com/WPdocument.php
import { ChildComponent } from "./my-feature/sub-component/deeper/.../my-deep.component";
```
* Follow Prettier standards, and consider using the [Prettier VSCode](https://marketplace.visualstudio.com/items?itemName=esbenp.prettier-vscode) plugin.
2. This is what I consider "leakage". The code is aware of the underlying implementation of the component.
3. It means the end user does not need to import and create the child component to be injected.
* Follow the `TSLint` rules
**Do not**
`TableFloatProperties` is a class. The outside world would have to construct the object, and inject it in
```js
public float(tableFloatProperties: TableFloatProperties): Table
```
**Do**
`ITableFloatOptions` is an interface for a JSON of primatives.
```js
public float(tableFloatOptions: ITableFloatOptions): Table
```
## Add vs Create
@ -64,7 +90,7 @@ Getters and Setters are done with a capital letter like so:
```js
public get Level() {
...
}
```
@ -130,7 +156,7 @@ enum WeaponType = {
## Spell correctly, full and in American English
I am not sure where these habit in software development comes from, but I do not believe it is beneficial:
I am not sure where these habits in software development come from, but I do not believe it is beneficial:
**Do not:**
```js

View File

@ -6,17 +6,17 @@
"scripts": {
"pretest": "rimraf ./build",
"test": "mocha-webpack \"src/**/*.ts\"",
"test-watch": "mocha-webpack \"src/**/*.ts\" --watch",
"test.coverage": "nyc npm test",
"test.watch": "npm test -- --watch",
"prepublishOnly": "npm run build",
"lint": "tslint --project .",
"build": "npm run webpack && npm run fix-types",
"tsc": "rimraf ./build && tsc -p .",
"webpack": "rimraf ./build && webpack",
"build.web": "webpack --config webpack.web.config.js",
"demo": "npm run build && npm run ts-node ./demo",
"typedoc": "typedoc src/index.ts",
"style": "prettier -l \"src/**/*.ts\"",
"style.fix": "prettier \"src/**/*.ts\" --write",
"style.fix": "npm run style -- --write",
"fix-types": "node types-absolute-fixer.js",
"ts-node": "ts-node"
},
@ -67,9 +67,11 @@
"awesome-typescript-loader": "^3.4.1",
"chai": "^3.5.0",
"glob": "^7.1.2",
"istanbul-instrumenter-loader": "^3.0.1",
"jszip": "^3.1.5",
"mocha": "^5.2.0",
"mocha-webpack": "^1.0.1",
"nyc": "^13.1.0",
"pre-commit": "^1.2.2",
"prettier": "^1.12.1",
"prompt": "^1.0.0",

View File

@ -1,6 +1,8 @@
/* tslint:disable:typedef space-before-function-paren */
import { expect } from "chai";
import { File } from "../../file";
import { File } from "file";
import { Compiler } from "./next-compiler";
describe("Compiler", () => {

View File

@ -2,7 +2,8 @@
import { assert } from "chai";
import { stub } from "sinon";
import { File, Paragraph } from "../../file";
import { File, Paragraph } from "file";
import { Packer } from "./packer";
describe("Packer", () => {

View File

@ -1,7 +1,9 @@
// tslint:disable:no-string-literal
import { expect } from "chai";
import { Formatter } from "../../export/formatter";
import { Formatter } from "export/formatter";
import { ContentTypes } from "./content-types";
describe("ContentTypes", () => {

View File

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

View File

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

View File

@ -1,7 +1,8 @@
import { expect } from "chai";
import { Formatter } from "../../../../../export/formatter";
import { BorderStyle } from "../../../../styles";
import { Formatter } from "export/formatter";
import { BorderStyle } from "file/styles";
import { PageBorderDisplay, PageBorders, PageBorderZOrder } from "./page-borders";
describe("PageBorders", () => {

View File

@ -1,6 +1,6 @@
// http://officeopenxml.com/WPsectionBorders.php
import { BorderStyle } from "file/styles";
import { IXmlableObject, XmlAttributeComponent, XmlComponent } from "file/xml-components";
import { BorderStyle } from "../../../../styles";
export enum PageBorderDisplay {
ALL_PAGES = "allPages",

View File

@ -1,6 +1,7 @@
import { expect } from "chai";
import { Formatter } from "../../../../../export/formatter";
import { Formatter } from "export/formatter";
import { PageSize } from "./page-size";
import { PageOrientation } from "./page-size-attributes";

View File

@ -1,14 +1,19 @@
import { expect } from "chai";
import { Formatter } from "../../../../export/formatter";
import { FooterWrapper } from "../../../footer-wrapper";
import { HeaderWrapper } from "../../../header-wrapper";
import { PageBorderOffsetFrom, PageNumberFormat } from "./";
import { Formatter } from "export/formatter";
import { FooterWrapper } from "file/footer-wrapper";
import { HeaderWrapper } from "file/header-wrapper";
import { Media } from "file/media";
import { PageBorderOffsetFrom } from "./page-border";
import { PageNumberFormat } from "./page-number";
import { SectionProperties } from "./section-properties";
describe("SectionProperties", () => {
describe("#constructor()", () => {
it("should create section properties with options", () => {
const media = new Media();
const properties = new SectionProperties({
width: 11906,
height: 16838,
@ -23,10 +28,10 @@ describe("SectionProperties", () => {
space: 708,
linePitch: 360,
headers: {
default: new HeaderWrapper(100),
default: new HeaderWrapper(media, 100),
},
footers: {
even: new FooterWrapper(200),
even: new FooterWrapper(media, 200),
},
pageNumberStart: 10,
pageNumberFormatType: PageNumberFormat.CARDINAL_TEXT,

View File

@ -1,8 +1,8 @@
// http://officeopenxml.com/WPsection.php
import { FooterWrapper } from "file/footer-wrapper";
import { HeaderWrapper } from "file/header-wrapper";
import { XmlComponent } from "file/xml-components";
import { FooterWrapper } from "../../../footer-wrapper";
import { HeaderWrapper } from "../../../header-wrapper";
import { IPageBordersOptions, IPageNumberTypeAttributes, PageBorders, PageNumberFormat, PageNumberType } from "./";
import { Columns } from "./columns/columns";
import { IColumnsAttributes } from "./columns/columns-attributes";
import { DocumentGrid } from "./doc-grid/doc-grid";
@ -11,8 +11,10 @@ import { FooterReferenceType } from "./footer-reference";
import { FooterReference } from "./footer-reference/footer-reference";
import { HeaderReferenceType } from "./header-reference";
import { HeaderReference } from "./header-reference/header-reference";
import { IPageBordersOptions, PageBorders } from "./page-border";
import { PageMargin } from "./page-margin/page-margin";
import { IPageMarginAttributes } from "./page-margin/page-margin-attributes";
import { IPageNumberTypeAttributes, PageNumberFormat, PageNumberType } from "./page-number";
import { PageSize } from "./page-size/page-size";
import { IPageSizeAttributes, PageOrientation } from "./page-size/page-size-attributes";
import { TitlePage } from "./title-page/title-page";

View File

@ -1,6 +1,7 @@
import { expect } from "chai";
import { Formatter } from "../../../../../export/formatter";
import { Formatter } from "export/formatter";
import { TitlePage } from "./title-page";
describe("PageSize", () => {

View File

@ -1,6 +1,7 @@
import { assert, expect } from "chai";
import { Formatter } from "../../export/formatter";
import { Formatter } from "export/formatter";
import { Paragraph } from "../paragraph";
import { Table } from "../table";
import { Document } from "./document";

View File

@ -1,8 +1,10 @@
import { assert } from "chai";
import { Utility } from "../../../tests/utility";
import { IDrawingOptions, TextWrapStyle } from ".././";
import { Anchor } from "./";
import { Utility } from "tests/utility";
import { IDrawingOptions } from "../drawing";
import { TextWrapStyle } from "../text-wrap";
import { Anchor } from "./anchor";
function createDrawing(drawingOptions: IDrawingOptions): Anchor {
return new Anchor(

View File

@ -1,7 +1,8 @@
import { assert } from "chai";
import { Utility } from "../../tests/utility";
import { Drawing, IDrawingOptions, PlacementPosition } from "./";
import { Utility } from "tests/utility";
import { Drawing, IDrawingOptions, PlacementPosition } from "./drawing";
const imageBase64Data = `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`;

View File

@ -1,4 +1,5 @@
import { XmlComponent } from "file/xml-components";
import { ExtentAttributes } from "./extent-attributes";
export class Extent extends XmlComponent {

View File

@ -1,8 +1,9 @@
import { assert } from "chai";
import { VerticalPositionAlign } from ".";
import { Utility } from "../../../tests/utility";
import { Utility } from "tests/utility";
import { Align } from "./align";
import { VerticalPositionAlign } from "./floating-position";
describe("Align", () => {
describe("#constructor()", () => {

View File

@ -1,7 +1,8 @@
import { assert } from "chai";
import { HorizontalPositionAlign, HorizontalPositionRelativeFrom } from ".";
import { Utility } from "../../../tests/utility";
import { Utility } from "tests/utility";
import { HorizontalPositionAlign, HorizontalPositionRelativeFrom } from "./floating-position";
import { HorizontalPosition } from "./horizontal-position";
describe("HorizontalPosition", () => {

View File

@ -1,6 +1,7 @@
import { assert } from "chai";
import { Utility } from "../../../tests/utility";
import { Utility } from "tests/utility";
import { PositionOffset } from "./position-offset";
describe("PositionOffset", () => {

View File

@ -1,6 +1,7 @@
import { assert } from "chai";
import { Utility } from "../../../tests/utility";
import { Utility } from "tests/utility";
import { SimplePos } from "./simple-pos";
describe("SimplePos", () => {

View File

@ -1,7 +1,8 @@
import { assert } from "chai";
import { VerticalPositionAlign, VerticalPositionRelativeFrom } from ".";
import { Utility } from "../../../tests/utility";
import { Utility } from "tests/utility";
import { VerticalPositionAlign, VerticalPositionRelativeFrom } from "./floating-position";
import { VerticalPosition } from "./vertical-position";
describe("VerticalPosition", () => {

View File

@ -173,13 +173,13 @@ export class File {
}
public createHeader(): HeaderWrapper {
const header = new HeaderWrapper(this.currentRelationshipId++);
const header = new HeaderWrapper(this.media, this.currentRelationshipId++);
this.addHeaderToDocument(header);
return header;
}
public createFooter(): FooterWrapper {
const footer = new FooterWrapper(this.currentRelationshipId++);
const footer = new FooterWrapper(this.media, this.currentRelationshipId++);
this.addFooterToDocument(footer);
return footer;
}

View File

@ -1,8 +1,8 @@
import { IMediaData } from "file/media";
import { XmlComponent } from "file/xml-components";
import { FooterReferenceType } from "./document";
import { Footer } from "./footer/footer";
import { Image, Media } from "./media";
import { Image, IMediaData, Media } from "./media";
import { ImageParagraph, Paragraph } from "./paragraph";
import { Relationships } from "./relationships";
import { Table } from "./table";
@ -15,10 +15,8 @@ export interface IDocumentFooter {
export class FooterWrapper {
private readonly footer: Footer;
private readonly relationships: Relationships;
private readonly media: Media;
constructor(referenceId: number, initContent?: XmlComponent) {
this.media = new Media();
constructor(private readonly media: Media, referenceId: number, initContent?: XmlComponent) {
this.footer = new Footer(referenceId, initContent);
this.relationships = new Relationships();
}
@ -48,7 +46,7 @@ export class FooterWrapper {
public addImageRelationship(image: Buffer, refId: number, width?: number, height?: number): IMediaData {
const mediaData = this.media.addMedia(image, refId, width, height);
this.relationships.createRelationship(
refId,
mediaData.referenceId,
"http://schemas.openxmlformats.org/officeDocument/2006/relationships/image",
`media/${mediaData.fileName}`,
);
@ -64,8 +62,10 @@ export class FooterWrapper {
);
}
public createImage(image: Buffer, width?: number, height?: number): void {
const mediaData = this.addImageRelationship(image, this.relationships.RelationshipCount, width, height);
public createImage(image: Buffer | string | Uint8Array | ArrayBuffer, width?: number, height?: number): void {
// TODO
// tslint:disable-next-line:no-any
const mediaData = this.addImageRelationship(image as any, this.relationships.RelationshipCount, width, height);
this.addImage(new Image(new ImageParagraph(mediaData)));
}

View File

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

View File

@ -1,5 +1,6 @@
import { Paragraph } from "file/paragraph";
import { XmlComponent } from "file/xml-components";
import { Paragraph } from "../../paragraph";
import { FootnoteAttributes } from "./footnote-attributes";
import { FootnoteRefRun } from "./run/footnote-ref-run";

View File

@ -1,8 +1,8 @@
import { IMediaData } from "file/media";
import { XmlComponent } from "file/xml-components";
import { HeaderReferenceType } from "./document";
import { Header } from "./header/header";
import { Image, Media } from "./media";
import { Image, IMediaData, Media } from "./media";
import { ImageParagraph, Paragraph } from "./paragraph";
import { Relationships } from "./relationships";
import { Table } from "./table";
@ -15,10 +15,8 @@ export interface IDocumentHeader {
export class HeaderWrapper {
private readonly header: Header;
private readonly relationships: Relationships;
private readonly media: Media;
constructor(referenceId: number, initContent?: XmlComponent) {
this.media = new Media();
constructor(private readonly media: Media, referenceId: number, initContent?: XmlComponent) {
this.header = new Header(referenceId, initContent);
this.relationships = new Relationships();
}
@ -48,7 +46,7 @@ export class HeaderWrapper {
public addImageRelationship(image: Buffer, refId: number, width?: number, height?: number): IMediaData {
const mediaData = this.media.addMedia(image, refId, width, height);
this.relationships.createRelationship(
refId,
mediaData.referenceId,
"http://schemas.openxmlformats.org/officeDocument/2006/relationships/image",
`media/${mediaData.fileName}`,
);
@ -64,8 +62,10 @@ export class HeaderWrapper {
);
}
public createImage(image: Buffer, width?: number, height?: number): void {
const mediaData = this.addImageRelationship(image, this.relationships.RelationshipCount, width, height);
public createImage(image: Buffer | string | Uint8Array | ArrayBuffer, width?: number, height?: number): void {
// TODO
// tslint:disable-next-line:no-any
const mediaData = this.addImageRelationship(image as any, this.relationships.RelationshipCount, width, height);
this.addImage(new Image(new ImageParagraph(mediaData)));
}

View File

@ -87,7 +87,7 @@ export class Media {
}
const imageData = {
referenceId: this.map.size + relationshipsCount + 1,
referenceId: relationshipsCount,
stream: data,
path: filePath,
fileName: key,

View File

@ -1,9 +1,11 @@
import { expect } from "chai";
import { Formatter } from "../../export/formatter";
import { Numbering } from "./";
import { Formatter } from "export/formatter";
import { AbstractNumbering } from "./abstract-numbering";
import { LevelForOverride } from "./level";
import { Num } from "./num";
import { Numbering } from "./numbering";
describe("Numbering", () => {
let numbering: Numbering;

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -1,7 +1,8 @@
// tslint:disable:object-literal-key-quotes
import { assert, expect } from "chai";
import { Formatter } from "../../export/formatter";
import { Formatter } from "export/formatter";
import { ImageParagraph } from "./image";
describe("Image", () => {

View File

@ -1,7 +1,8 @@
import { assert } from "chai";
import { Utility } from "../../../tests/utility";
import { Bookmark } from "./";
import { Utility } from "tests/utility";
import { Bookmark } from "./bookmark";
describe("Bookmark", () => {
let bookmark: Bookmark;

View File

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

View File

@ -1,7 +1,8 @@
import { assert, expect } from "chai";
import { Formatter } from "../../export/formatter";
import * as file from "../../file";
import { Formatter } from "export/formatter";
import * as file from "file";
import { Numbering } from "../numbering";
describe("Paragraph", () => {

View File

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

View File

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

View File

@ -1,6 +1,7 @@
import { expect } from "chai";
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 { Formatter } from "../../../export/formatter";
import { Utility } from "../../../tests/utility";
import { Formatter } from "export/formatter";
import { Utility } from "tests/utility";
import { Run } from "./";
describe("Run", () => {

View File

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

View File

@ -1,6 +1,7 @@
import { expect } from "chai";
import { Formatter } from "../../../export/formatter";
import { Formatter } from "export/formatter";
import { SequentialIdentifier } from "./sequential-identifier";
describe("Sequential Identifier", () => {

View File

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

View File

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

View File

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

View File

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

View File

@ -1,7 +1,8 @@
// tslint:disable:no-string-literal
import { expect } from "chai";
import { Formatter } from "../../export/formatter";
import { Formatter } from "export/formatter";
import { Relationships } from "./relationships";
describe("Relationships", () => {

View File

@ -1,6 +1,9 @@
import { expect } from "chai";
import { Formatter } from "../../export/formatter";
import { Settings } from "./";
import { Formatter } from "export/formatter";
import { Settings } from "./settings";
describe("Settings", () => {
describe("#constructor", () => {
it("should create a empty Settings with correct rootKey", () => {

View File

@ -1,6 +1,9 @@
import { expect } from "chai";
import { Formatter } from "../../export/formatter";
import { UpdateFields } from "./";
import { Formatter } from "export/formatter";
import { UpdateFields } from "./update-fields";
const UF_TRUE = {
"w:updateFields": [
{

View File

@ -1,5 +1,5 @@
import { ParagraphProperties } from "file/paragraph/properties";
import { XmlComponent } from "file/xml-components";
import { ParagraphProperties } from "../../paragraph/properties";
export class ParagraphPropertiesDefaults extends XmlComponent {
constructor() {

View File

@ -1,7 +1,7 @@
import { Size, SizeComplexScript } from "file/paragraph/run/formatting";
import { RunProperties } from "file/paragraph/run/properties";
import { RunFonts } from "file/paragraph/run/run-fonts";
import { XmlComponent } from "file/xml-components";
import { Size, SizeComplexScript } from "../../paragraph/run/formatting";
import { RunProperties } from "../../paragraph/run/properties";
import { RunFonts } from "../../paragraph/run/run-fonts";
export class RunPropertiesDefaults extends XmlComponent {
private readonly properties: RunProperties;

View File

@ -1,30 +1 @@
import { BaseXmlComponent, XmlComponent } from "file/xml-components";
import { DocumentDefaults } from "./defaults";
import { ParagraphStyle } from "./style";
export * from "./border";
export class Styles extends XmlComponent {
constructor(initialStyles?: BaseXmlComponent) {
super("w:styles");
if (initialStyles) {
this.root.push(initialStyles);
}
}
public push(style: XmlComponent): Styles {
this.root.push(style);
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);
return para;
}
}
export * from "./styles";

View File

@ -1,7 +1,7 @@
import * as paragraph from "file/paragraph";
import * as formatting from "file/paragraph/run/formatting";
import { RunProperties } from "file/paragraph/run/properties";
import { XmlAttributeComponent, XmlComponent } from "file/xml-components";
import * as paragraph from "../../paragraph";
import * as formatting from "../../paragraph/run/formatting";
import { RunProperties } from "../../paragraph/run/properties";
import { BasedOn, Link, Name, Next, QuickFormat, SemiHidden, UiPriority, UnhideWhenUsed } from "./components";

View File

@ -1,8 +1,10 @@
import { assert, expect } from "chai";
import { Formatter } from "../../export/formatter";
import { Styles } from "./";
import { Formatter } from "export/formatter";
import { ParagraphStyle, Style } from "./style";
import * as components from "./style/components";
import { Styles } from "./styles";
describe("Styles", () => {
let styles: Styles;

30
src/file/styles/styles.ts Normal file
View File

@ -0,0 +1,30 @@
import { BaseXmlComponent, XmlComponent } from "file/xml-components";
import { DocumentDefaults } from "./defaults";
import { ParagraphStyle } from "./style";
export * from "./border";
export class Styles extends XmlComponent {
constructor(initialStyles?: BaseXmlComponent) {
super("w:styles");
if (initialStyles) {
this.root.push(initialStyles);
}
}
public push(style: XmlComponent): Styles {
this.root.push(style);
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);
return para;
}
}

View File

@ -56,7 +56,7 @@ export class FieldInstruction extends XmlComponent {
instruction = `${instruction} \\s "${this.properties.seqFieldIdentifierForPrefix}"`;
}
if (this.properties.stylesWithLevels && this.properties.stylesWithLevels.length) {
const styles = this.properties.stylesWithLevels.map((sl) => `${sl.styleName},${sl.level}`).join(",");
const styles = this.properties.stylesWithLevels.map((sl) => `${sl.styleName};${sl.level}`).join(";");
instruction = `${instruction} \\t "${styles}"`;
}
if (this.properties.useAppliedParagraphOutlineLevel) {

View File

@ -1,7 +1,9 @@
import { expect } from "chai";
import { Formatter } from "../../export/formatter";
import { ITableOfContentsOptions, StyleLevel, TableOfContents } from "./";
import { Formatter } from "export/formatter";
import { TableOfContents } from "./table-of-contents";
import { ITableOfContentsOptions, StyleLevel } from "./table-of-contents-properties";
describe("Table of Contents", () => {
describe("#constructor", () => {
@ -174,7 +176,7 @@ const COMPLETE_TOC = {
"xml:space": "preserve",
},
},
'TOC \\a "A" \\b "B" \\c "C" \\d "D" \\f "F" \\h \\l "L" \\n "N" \\o "O" \\p "P" \\s "S" \\t "SL,1,SL,2" \\u \\w \\x \\z',
'TOC \\a "A" \\b "B" \\c "C" \\d "D" \\f "F" \\h \\l "L" \\n "N" \\o "O" \\p "P" \\s "S" \\t "SL;1;SL;2" \\u \\w \\x \\z',
],
},
{

View File

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

View File

@ -1,2 +1,3 @@
export * from "./table";
export * from "./table-cell";
export * from "./table-properties";

View File

@ -1,97 +0,0 @@
import { XmlAttributeComponent, XmlComponent } from "file/xml-components";
import { WidthType } from "./table-cell";
import { TableCellMargin } from "./table-cell-margin";
export class TableProperties extends XmlComponent {
private readonly cellMargin: TableCellMargin;
constructor() {
super("w:tblPr");
this.cellMargin = new TableCellMargin();
this.root.push(this.cellMargin);
}
public setWidth(type: WidthType, w: number | string): TableProperties {
this.root.push(new PreferredTableWidth(type, w));
return this;
}
public setFixedWidthLayout(): TableProperties {
this.root.push(new TableLayout("fixed"));
return this;
}
public setBorder(): TableProperties {
this.root.push(new TableBorders());
return this;
}
public get CellMargin(): TableCellMargin {
return this.cellMargin;
}
}
interface ITableWidth {
type: WidthType;
w: number | string;
}
class TableWidthAttributes extends XmlAttributeComponent<ITableWidth> {
protected xmlKeys = { type: "w:type", w: "w:w" };
}
class PreferredTableWidth extends XmlComponent {
constructor(type: WidthType, w: number | string) {
super("w:tblW");
this.root.push(new TableWidthAttributes({ type, w }));
}
}
type TableLayoutOptions = "autofit" | "fixed";
class TableLayoutAttributes extends XmlAttributeComponent<{ type: TableLayoutOptions }> {
protected xmlKeys = { type: "w:type" };
}
class TableLayout extends XmlComponent {
constructor(type: TableLayoutOptions) {
super("w:tblLayout");
this.root.push(new TableLayoutAttributes({ type }));
}
}
class TableBorders extends XmlComponent {
constructor() {
super("w:tblBorders");
this.root.push(new TableBordersElement("w:top", "single", 4, 0, "auto"));
this.root.push(new TableBordersElement("w:left", "single", 4, 0, "auto"));
this.root.push(new TableBordersElement("w:bottom", "single", 4, 0, "auto"));
this.root.push(new TableBordersElement("w:right", "single", 4, 0, "auto"));
this.root.push(new TableBordersElement("w:insideH", "single", 4, 0, "auto"));
this.root.push(new TableBordersElement("w:insideV", "single", 4, 0, "auto"));
}
}
class TableBordersElement extends XmlComponent {
constructor(elementName: string, value: string, size: number, space: number, color: string) {
super(elementName);
this.root.push(
new TableBordersAttributes({
value,
size,
space,
color,
}),
);
}
}
class TableBordersAttributes extends XmlAttributeComponent<{ value: string; size: number; space: number; color: string }> {
protected xmlKeys = {
value: "w:val",
size: "w:sz",
space: "w:space",
color: "w:color",
};
}

View File

@ -0,0 +1,2 @@
export * from "./table-cell";
export * from "./table-cell-components";

View File

@ -1,5 +1,5 @@
import { BorderStyle } from "file/styles";
import { IXmlableObject, XmlAttributeComponent, XmlComponent } from "file/xml-components";
import { BorderStyle } from "../styles";
interface ICellBorder {
style: BorderStyle;

View File

@ -0,0 +1,57 @@
import { XmlComponent } from "file/xml-components";
import {
GridSpan,
TableCellBorders,
TableCellShading,
TableCellWidth,
VAlign,
VerticalAlign,
VMerge,
VMergeType,
WidthType,
} from "./table-cell-components";
export class TableCellProperties extends XmlComponent {
private readonly cellBorder: TableCellBorders;
constructor() {
super("w:tcPr");
this.cellBorder = new TableCellBorders();
this.root.push(this.cellBorder);
}
public get Borders(): TableCellBorders {
return this.cellBorder;
}
public addGridSpan(cellSpan: number): TableCellProperties {
this.root.push(new GridSpan(cellSpan));
return this;
}
public addVerticalMerge(type: VMergeType): TableCellProperties {
this.root.push(new VMerge(type));
return this;
}
public setVerticalAlign(type: VerticalAlign): TableCellProperties {
this.root.push(new VAlign(type));
return this;
}
public setWidth(width: string | number, type: WidthType): TableCellProperties {
this.root.push(new TableCellWidth(width, type));
return this;
}
public setShading(attrs: object): TableCellProperties {
this.root.push(new TableCellShading(attrs));
return this;
}
}

View File

@ -1,8 +1,9 @@
import { expect } from "chai";
import { Formatter } from "../../export/formatter";
import { BorderStyle } from "../styles";
import { TableCellBorders, TableCellWidth, WidthType } from "./table-cell";
import { Formatter } from "export/formatter";
import { BorderStyle } from "file/styles";
import { TableCellBorders, TableCellWidth, WidthType } from "./table-cell-components";
describe("TableCellBorders", () => {
describe("#prepForXml", () => {

View File

@ -0,0 +1,45 @@
// http://officeopenxml.com/WPtableGrid.php
import { Paragraph } from "file/paragraph";
import { IXmlableObject, XmlComponent } from "file/xml-components";
import { Table } from "../table";
import { TableCellProperties } from "./table-cell-properties";
export class TableCell extends XmlComponent {
private readonly properties: TableCellProperties;
constructor() {
super("w:tc");
this.properties = new TableCellProperties();
this.root.push(this.properties);
}
public addContent(content: Paragraph | Table): TableCell {
this.root.push(content);
return this;
}
public prepForXml(): IXmlableObject | undefined {
// Cells must end with a paragraph
const retval = super.prepForXml();
if (!retval) {
return undefined;
}
const content = retval["w:tc"];
if (!content[content.length - 1]["w:p"]) {
content.push(new Paragraph().prepForXml());
}
return retval;
}
public createParagraph(text?: string): Paragraph {
const para = new Paragraph(text);
this.addContent(para);
return para;
}
public get CellProperties(): TableCellProperties {
return this.properties;
}
}

View File

@ -0,0 +1,2 @@
export * from "./table-properties";
export * from "./table-float-properties";

View File

@ -0,0 +1,36 @@
import { XmlAttributeComponent, XmlComponent } from "file/xml-components";
export class TableBorders extends XmlComponent {
constructor() {
super("w:tblBorders");
this.root.push(new TableBordersElement("w:top", "single", 4, 0, "auto"));
this.root.push(new TableBordersElement("w:left", "single", 4, 0, "auto"));
this.root.push(new TableBordersElement("w:bottom", "single", 4, 0, "auto"));
this.root.push(new TableBordersElement("w:right", "single", 4, 0, "auto"));
this.root.push(new TableBordersElement("w:insideH", "single", 4, 0, "auto"));
this.root.push(new TableBordersElement("w:insideV", "single", 4, 0, "auto"));
}
}
class TableBordersElement extends XmlComponent {
constructor(elementName: string, value: string, size: number, space: number, color: string) {
super(elementName);
this.root.push(
new TableBordersAttributes({
value,
size,
space,
color,
}),
);
}
}
class TableBordersAttributes extends XmlAttributeComponent<{ value: string; size: number; space: number; color: string }> {
protected xmlKeys = {
value: "w:val",
size: "w:sz",
space: "w:space",
color: "w:color",
};
}

View File

@ -1,5 +1,6 @@
import { IXmlableObject, XmlAttributeComponent, XmlComponent } from "file/xml-components";
import { WidthType } from "./table-cell";
import { WidthType } from "../table-cell";
class TableCellMarginAttributes extends XmlAttributeComponent<{ type: WidthType; value: number }> {
protected xmlKeys = { value: "w:w", type: "w:sz" };

View File

@ -0,0 +1,45 @@
import { expect } from "chai";
import { Formatter } from "export/formatter";
import { RelativeHorizontalPosition, RelativeVerticalPosition, TableAnchorType, TableFloatProperties } from "./table-float-properties";
describe("Table Float Properties", () => {
describe("#constructor", () => {
it("should construct a TableFloatProperties with all options", () => {
const tfp = new TableFloatProperties({
horizontalAnchor: TableAnchorType.MARGIN,
verticalAnchor: TableAnchorType.PAGE,
absoluteHorizontalPosition: 10,
relativeHorizontalPosition: RelativeHorizontalPosition.CENTER,
absoluteVerticalPosition: 20,
relativeVerticalPosition: RelativeVerticalPosition.BOTTOM,
bottomFromText: 30,
topFromText: 40,
leftFromText: 50,
rightFromText: 60,
});
const tree = new Formatter().format(tfp);
expect(tree).to.be.deep.equal(DEFAULT_TFP);
});
});
});
const DEFAULT_TFP = {
"w:tblpPr": [
{
_attr: {
"w:horzAnchor": "margin",
"w:vertAnchor": "page",
"w:tblpX": 10,
"w:tblpXSpec": "center",
"w:tblpY": 20,
"w:tblpYSpec": "bottom",
"w:bottomFromText": 30,
"w:topFromText": 40,
"w:leftFromText": 50,
"w:rightFromText": 60,
},
},
],
};

View File

@ -0,0 +1,134 @@
import { XmlAttributeComponent, XmlComponent } from "file/xml-components";
export enum TableAnchorType {
MARGIN = "margin",
PAGE = "page",
TEXT = "text",
}
export enum RelativeHorizontalPosition {
CENTER = "center",
INSIDE = "inside",
LEFT = "left",
OUTSIDE = "outside",
RIGHT = "right",
}
export enum RelativeVerticalPosition {
CENTER = "center",
INSIDE = "inside",
BOTTOM = "bottom",
OUTSIDE = "outside",
INLINE = "inline",
TOP = "top",
}
export interface ITableFloatOptions {
/**
* Specifies the horizontal anchor or the base object from which the horizontal positioning in the
* tblpX or tblpXSpec attribute should be determined.
* margin - relative to the vertical edge of the text margin before any text runs (left edge for left-to-right paragraphs)
* page - relative to the vertical edge of the page before any text runs (left edge for left-to-right paragraphs)
* text - relative to the vertical edge of the text margin for the column in which the anchor paragraph is located
* If omitted, the value is assumed to be page.
*/
horizontalAnchor?: TableAnchorType;
/**
* Specifies an absolute horizontal position for the table, relative to the horizontalAnchor.
* The value is in twentieths of a point. Note that the value can be negative, in which case the
* table is positioned before the anchor object in the direction of horizontal text flow.
* If relativeHorizontalPosition is also specified, then the absoluteHorizontalPosition attribute is ignored.
* If the attribute is omitted, the value is assumed to be zero.
*/
absoluteHorizontalPosition?: number;
/**
* Specifies a relative horizontal position for the table, relative to the horizontalAnchor attribute.
* This will supersede the absoluteHorizontalPosition attribute.
* Possible values are:
* center - the table should be horizontally centered with respect to the anchor
* inside - the table should be inside of the anchor
* left - the table should be left aligned with respect to the anchor
* outside - the table should be outside of the anchor
* right - the table should be right aligned with respect to the anchor
*/
relativeHorizontalPosition?: RelativeHorizontalPosition;
/**
* Specifies the vertical anchor or the base object from which the vertical positioning
* in the absoluteVerticalPosition attribute should be determined. Possible values are:
* margin - relative to the horizontal edge of the text margin before any text runs (top edge for top-to-bottom paragraphs)
* page - relative to the horizontal edge of the page before any text runs (top edge for top-to-bottom paragraphs)
* text - relative to the horizontal edge of the text margin for the column in which the anchor paragraph is located
* If omitted, the value is assumed to be page.
*/
verticalAnchor?: TableAnchorType;
/**
* Specifies an absolute vertical position for the table, relative to the verticalAnchor anchor.
* The value is in twentieths of a point. Note that the value can be negative, in which case the table is
* positioned before the anchor object in the direction of vertical text flow.
* If relativeVerticalPosition is also specified, then the absoluteVerticalPosition attribute is ignored.
* If the attribute is omitted, the value is assumed to be zero.
*/
absoluteVerticalPosition?: number;
/**
* Specifies a relative vertical position for the table, relative to the verticalAnchor attribute.
* This will supersede the absoluteVerticalPosition attribute. Possible values are:
* center - the table should be vertically centered with respect to the anchor
* inside - the table should be vertically aligned to the edge of the anchor and inside the anchor
* bottom - the table should be vertically aligned to the bottom edge of the anchor
* outside - the table should be vertically aligned to the edge of the anchor and outside the anchor
* inline - the table should be vertically aligned in line with the surrounding text (so as to not allow any text wrapping around it)
* top - the table should be vertically aligned to the top edge of the anchor
*/
relativeVerticalPosition?: RelativeVerticalPosition;
/**
* Specifies the minimun distance to be maintained between the table and the top of text in the paragraph
* below the table. The value is in twentieths of a point. If omitted, the value is assumed to be zero.
*/
bottomFromText?: number;
/**
* Specifies the minimun distance to be maintained between the table and the bottom edge of text in the paragraph
* above the table. The value is in twentieths of a point. If omitted, the value is assumed to be zero.
*/
topFromText?: number;
/**
* Specifies the minimun distance to be maintained between the table and the edge of text in the paragraph
* to the left of the table. The value is in twentieths of a point. If omitted, the value is assumed to be zero.
*/
leftFromText?: number;
/**
* Specifies the minimun distance to be maintained between the table and the edge of text in the paragraph
* to the right of the table. The value is in twentieths of a point. If omitted, the value is assumed to be zero.
*/
rightFromText?: number;
}
export class TableFloatOptionsAttributes extends XmlAttributeComponent<ITableFloatOptions> {
protected xmlKeys = {
horizontalAnchor: "w:horzAnchor",
verticalAnchor: "w:vertAnchor",
absoluteHorizontalPosition: "w:tblpX",
relativeHorizontalPosition: "w:tblpXSpec",
absoluteVerticalPosition: "w:tblpY",
relativeVerticalPosition: "w:tblpYSpec",
bottomFromText: "w:bottomFromText",
topFromText: "w:topFromText",
leftFromText: "w:leftFromText",
rightFromText: "w:rightFromText",
};
}
export class TableFloatProperties extends XmlComponent {
constructor(options: ITableFloatOptions) {
super("w:tblpPr");
this.root.push(new TableFloatOptionsAttributes(options));
}
}

View File

@ -0,0 +1,17 @@
import { XmlAttributeComponent, XmlComponent } from "file/xml-components";
export enum TableLayoutType {
AUTOFIT = "autofit",
FIXED = "fixed",
}
class TableLayoutAttributes extends XmlAttributeComponent<{ type: TableLayoutType }> {
protected xmlKeys = { type: "w:type" };
}
export class TableLayout extends XmlComponent {
constructor(type: TableLayoutType) {
super("w:tblLayout");
this.root.push(new TableLayoutAttributes({ type }));
}
}

View File

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

View File

@ -0,0 +1,43 @@
import { XmlComponent } from "file/xml-components";
import { WidthType } from "../table-cell";
import { TableBorders } from "./table-borders";
import { TableCellMargin } from "./table-cell-margin";
import { ITableFloatOptions, TableFloatProperties } from "./table-float-properties";
import { TableLayout, TableLayoutType } from "./table-layout";
import { PreferredTableWidth } from "./table-width";
export class TableProperties extends XmlComponent {
private readonly cellMargin: TableCellMargin;
constructor() {
super("w:tblPr");
this.cellMargin = new TableCellMargin();
this.root.push(this.cellMargin);
}
public setWidth(type: WidthType, w: number | string): TableProperties {
this.root.push(new PreferredTableWidth(type, w));
return this;
}
public setFixedWidthLayout(): TableProperties {
this.root.push(new TableLayout(TableLayoutType.FIXED));
return this;
}
public setBorder(): TableProperties {
this.root.push(new TableBorders());
return this;
}
public get CellMargin(): TableCellMargin {
return this.cellMargin;
}
public setTableFloatProperties(tableFloatOptions: ITableFloatOptions): TableProperties {
this.root.push(new TableFloatProperties(tableFloatOptions));
return this;
}
}

View File

@ -0,0 +1,19 @@
import { XmlAttributeComponent, XmlComponent } from "file/xml-components";
import { WidthType } from "../table-cell";
interface ITableWidth {
type: WidthType;
w: number | string;
}
class TableWidthAttributes extends XmlAttributeComponent<ITableWidth> {
protected xmlKeys = { type: "w:type", w: "w:w" };
}
export class PreferredTableWidth extends XmlComponent {
constructor(type: WidthType, w: number | string) {
super("w:tblW");
this.root.push(new TableWidthAttributes({ type, w }));
}
}

View File

@ -0,0 +1,2 @@
export * from "./table-row";
export * from "./table-row-properties";

View File

@ -0,0 +1,7 @@
import { XmlComponent } from "file/xml-components";
export class TableRowProperties extends XmlComponent {
constructor() {
super("w:trPr");
}
}

View File

@ -0,0 +1,40 @@
import { XmlComponent } from "file/xml-components";
import { TableCell } from "../table-cell";
import { TableRowProperties } from "./table-row-properties";
export class TableRow extends XmlComponent {
private readonly properties: TableRowProperties;
constructor(private readonly cells: TableCell[]) {
super("w:tr");
this.properties = new TableRowProperties();
this.root.push(this.properties);
cells.forEach((c) => this.root.push(c));
}
public getCell(ix: number): TableCell {
const cell = this.cells[ix];
if (!cell) {
throw Error("Index out of bounds when trying to get cell on row");
}
return cell;
}
public addGridSpan(index: number, cellSpan: number): TableCell {
const remainCell = this.cells[index];
remainCell.CellProperties.addGridSpan(cellSpan);
this.cells.splice(index + 1, cellSpan - 1);
this.root.splice(index + 2, cellSpan - 1);
return remainCell;
}
public mergeCells(startIndex: number, endIndex: number): TableCell {
const cellSpan = endIndex - startIndex + 1;
return this.addGridSpan(startIndex, cellSpan);
}
}

View File

@ -1,10 +1,12 @@
/* tslint:disable:no-unused-expression */
import { expect } from "chai";
import { Formatter } from "../../export/formatter";
import { Formatter } from "export/formatter";
import { Paragraph } from "../paragraph";
import { Table } from "./";
import { Table } from "./table";
import { WidthType } from "./table-cell";
import { RelativeHorizontalPosition, RelativeVerticalPosition, TableAnchorType } from "./table-properties";
const DEFAULT_TABLE_PROPERTIES = {
"w:tblBorders": [
@ -294,4 +296,49 @@ describe("Table", () => {
});
});
});
describe("#float", () => {
it("sets the table float properties", () => {
const table = new Table(1, 1).float({
horizontalAnchor: TableAnchorType.MARGIN,
verticalAnchor: TableAnchorType.PAGE,
absoluteHorizontalPosition: 10,
relativeHorizontalPosition: RelativeHorizontalPosition.CENTER,
absoluteVerticalPosition: 20,
relativeVerticalPosition: RelativeVerticalPosition.BOTTOM,
bottomFromText: 30,
topFromText: 40,
leftFromText: 50,
rightFromText: 60,
});
const tree = new Formatter().format(table);
expect(tree)
.to.have.property("w:tbl")
.which.is.an("array")
.with.has.length.at.least(1);
expect(tree["w:tbl"][0]).to.deep.equal({
"w:tblPr": [
DEFAULT_TABLE_PROPERTIES,
{
"w:tblpPr": [
{
_attr: {
"w:horzAnchor": "margin",
"w:vertAnchor": "page",
"w:tblpX": 10,
"w:tblpXSpec": "center",
"w:tblpY": 20,
"w:tblpYSpec": "bottom",
"w:bottomFromText": 30,
"w:topFromText": 40,
"w:leftFromText": 50,
"w:rightFromText": 60,
},
},
],
},
],
});
});
});
});

View File

@ -1,19 +1,10 @@
// http://officeopenxml.com/WPtableGrid.php
import {
GridSpan,
TableCellBorders,
TableCellShading,
TableCellWidth,
VAlign,
VerticalAlign,
VMerge,
VMergeType,
WidthType,
} from "file/table/table-cell";
import { IXmlableObject, XmlComponent } from "file/xml-components";
import { Paragraph } from "../paragraph";
import { XmlComponent } from "file/xml-components";
import { TableGrid } from "./grid";
import { TableProperties } from "./properties";
import { TableCell, WidthType } from "./table-cell";
import { ITableFloatOptions, TableProperties } from "./table-properties";
import { TableRow } from "./table-row";
export class Table extends XmlComponent {
private readonly properties: TableProperties;
@ -84,132 +75,12 @@ export class Table extends XmlComponent {
return this;
}
public float(tableFloatOptions: ITableFloatOptions): Table {
this.properties.setTableFloatProperties(tableFloatOptions);
return this;
}
public get Properties(): TableProperties {
return this.properties;
}
}
export class TableRow extends XmlComponent {
private readonly properties: TableRowProperties;
constructor(private readonly cells: TableCell[]) {
super("w:tr");
this.properties = new TableRowProperties();
this.root.push(this.properties);
cells.forEach((c) => this.root.push(c));
}
public getCell(ix: number): TableCell {
const cell = this.cells[ix];
if (!cell) {
throw Error("Index out of bounds when trying to get cell on row");
}
return cell;
}
public addGridSpan(index: number, cellSpan: number): TableCell {
const remainCell = this.cells[index];
remainCell.CellProperties.addGridSpan(cellSpan);
this.cells.splice(index + 1, cellSpan - 1);
this.root.splice(index + 2, cellSpan - 1);
return remainCell;
}
public mergeCells(startIndex: number, endIndex: number): TableCell {
const cellSpan = endIndex - startIndex + 1;
return this.addGridSpan(startIndex, cellSpan);
}
}
export class TableRowProperties extends XmlComponent {
constructor() {
super("w:trPr");
}
}
export class TableCell extends XmlComponent {
private readonly properties: TableCellProperties;
constructor() {
super("w:tc");
this.properties = new TableCellProperties();
this.root.push(this.properties);
}
public addContent(content: Paragraph | Table): TableCell {
this.root.push(content);
return this;
}
public prepForXml(): IXmlableObject | undefined {
// Cells must end with a paragraph
const retval = super.prepForXml();
if (!retval) {
return undefined;
}
const content = retval["w:tc"];
if (!content[content.length - 1]["w:p"]) {
content.push(new Paragraph().prepForXml());
}
return retval;
}
public createParagraph(text?: string): Paragraph {
const para = new Paragraph(text);
this.addContent(para);
return para;
}
public get CellProperties(): TableCellProperties {
return this.properties;
}
}
export class TableCellProperties extends XmlComponent {
private readonly cellBorder: TableCellBorders;
constructor() {
super("w:tcPr");
this.cellBorder = new TableCellBorders();
this.root.push(this.cellBorder);
}
public get Borders(): TableCellBorders {
return this.cellBorder;
}
public addGridSpan(cellSpan: number): TableCellProperties {
this.root.push(new GridSpan(cellSpan));
return this;
}
public addVerticalMerge(type: VMergeType): TableCellProperties {
this.root.push(new VMerge(type));
return this;
}
public setVerticalAlign(type: VerticalAlign): TableCellProperties {
this.root.push(new VAlign(type));
return this;
}
public setWidth(width: string | number, type: WidthType): TableCellProperties {
this.root.push(new TableCellWidth(width, type));
return this;
}
public setShading(attrs: object): TableCellProperties {
this.root.push(new TableCellShading(attrs));
return this;
}
}

View File

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

View File

@ -7,6 +7,7 @@ import { FooterWrapper, IDocumentFooter } from "file/footer-wrapper";
import { HeaderWrapper, IDocumentHeader } from "file/header-wrapper";
import { convertToXmlComponent, ImportedXmlComponent } from "file/xml-components";
import { Media } from "file/media";
import { Styles } from "file/styles";
import { ExternalStylesFactory } from "file/styles/external-styles-factory";
@ -59,6 +60,8 @@ export class ImportDotx {
const relationshipContent = zipContent.files["word/_rels/document.xml.rels"];
const documentRelationships: IRelationshipFileInfo[] = this.findReferenceFiles(await relationshipContent.async("text"));
const media = new Media();
const headers: IDocumentHeader[] = [];
for (const headerRef of documentRefs.headers) {
const relationFileInfo = documentRelationships.find((rel) => rel.id === headerRef.id);
@ -78,7 +81,7 @@ export class ImportDotx {
continue;
}
const importedComp = convertToXmlComponent(headerXmlElement) as ImportedXmlComponent;
const header = new HeaderWrapper(this.currentRelationshipId++, importedComp);
const header = new HeaderWrapper(media, this.currentRelationshipId++, importedComp);
await this.addRelationToWrapper(relationFileInfo, zipContent, header);
headers.push({ type: headerRef.type, header });
}
@ -101,7 +104,7 @@ export class ImportDotx {
continue;
}
const importedComp = convertToXmlComponent(footerXmlElement) as ImportedXmlComponent;
const footer = new FooterWrapper(this.currentRelationshipId++, importedComp);
const footer = new FooterWrapper(media, this.currentRelationshipId++, importedComp);
await this.addRelationToWrapper(relationFileInfo, zipContent, footer);
footers.push({ type: footerRef.type, footer });
}
@ -117,13 +120,13 @@ export class ImportDotx {
}
public async addRelationToWrapper(
relationFile: IRelationshipFileInfo,
relationhipFile: IRelationshipFileInfo,
zipContent: JSZip,
wrapper: HeaderWrapper | FooterWrapper,
): Promise<void> {
let wrapperImagesReferences: IRelationshipFileInfo[] = [];
let hyperLinkReferences: IRelationshipFileInfo[] = [];
const refFile = zipContent.files[`word/_rels/${relationFile.target}.rels`];
const refFile = zipContent.files[`word/_rels/${relationhipFile.target}.rels`];
if (refFile) {
const xmlRef = await refFile.async("text");
wrapperImagesReferences = this.findReferenceFiles(xmlRef).filter((r) => r.type === "image");
@ -143,7 +146,7 @@ export class ImportDotx {
const relationXmlArray = Array.isArray(xmlObj.Relationships.Relationship)
? xmlObj.Relationships.Relationship
: [xmlObj.Relationships.Relationship];
const relations: IRelationshipFileInfo[] = relationXmlArray
const relationships: IRelationshipFileInfo[] = relationXmlArray
.map((item: XMLElementCompact) => {
if (item._attributes === undefined) {
throw Error("relationship element has no attributes");
@ -155,7 +158,7 @@ export class ImportDotx {
};
})
.filter((item) => item.type !== null);
return relations;
return relationships;
}
public extractDocumentRefs(xmlData: string): IDocumentRefs {

View File

@ -20,6 +20,14 @@ module.exports = {
test: /\.ts$/,
loaders: ["awesome-typescript-loader"],
},
{
// For coverage testing
test: /\.(ts)/,
include: path.resolve("src"),
loader: "istanbul-instrumenter-loader",
enforce: "post",
exclude: [/node_modules/],
}
],
},