diff --git a/.gitignore b/.gitignore index e6143b4db7..8a7c8baf67 100644 --- a/.gitignore +++ b/.gitignore @@ -58,5 +58,8 @@ yarn.lock # Documents My Document.docx -# Temporary folder -tmp \ No newline at end of file +# Temporary folder +tmp + +# nyc +.nyc_output diff --git a/.nycrc b/.nycrc new file mode 100644 index 0000000000..7c878bae51 --- /dev/null +++ b/.nycrc @@ -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 +} diff --git a/.travis.yml b/.travis.yml index 373070eeb8..e84682f2da 100644 --- a/.travis.yml +++ b/.travis.yml @@ -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 diff --git a/README.md b/README.md index f387c41a14..f9120883e0 100644 --- a/README.md +++ b/README.md @@ -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]

drawing @@ -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 diff --git a/demo/demo23.ts b/demo/demo23.ts index 47ee26a6f9..2e230e0cb7 100644 --- a/demo/demo23.ts +++ b/demo/demo23.ts @@ -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); diff --git a/demo/demo24.ts b/demo/demo24.ts index 23828aec65..4901477ced 100644 --- a/demo/demo24.ts +++ b/demo/demo24.ts @@ -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(); diff --git a/demo/demo34.ts b/demo/demo34.ts new file mode 100644 index 0000000000..098e1c2065 --- /dev/null +++ b/demo/demo34.ts @@ -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); +}); diff --git a/docs/contribution-guidelines.md b/docs/contribution-guidelines.md index a212a081c2..9bc1d4c90d 100644 --- a/docs/contribution-guidelines.md +++ b/docs/contribution-guidelines.md @@ -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. - ```js - // http://officeopenxml.com/WPdocument.php - ``` +Try to make method parameters accept primatives, or `json` objects, so that child components are created **inside** the component, rather than being **injected** in. -* Follow Prettier standards, and consider using the [Prettier VSCode](https://marketplace.visualstudio.com/items?itemName=esbenp.prettier-vscode) plugin. +This is so that: -* Follow the `TSLint` rules +1. Imports are much cleaner, no need for: + ```js + import { ChildComponent } from "./my-feature/sub-component/deeper/.../my-deep.component"; + ``` + +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. + +**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 diff --git a/package.json b/package.json index 8c74524dd3..c111fec200 100644 --- a/package.json +++ b/package.json @@ -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", diff --git a/src/export/packer/next-compiler.spec.ts b/src/export/packer/next-compiler.spec.ts index 774b71c26f..2ac32dda33 100644 --- a/src/export/packer/next-compiler.spec.ts +++ b/src/export/packer/next-compiler.spec.ts @@ -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", () => { diff --git a/src/export/packer/packer.spec.ts b/src/export/packer/packer.spec.ts index 497e3e46b7..110089da01 100644 --- a/src/export/packer/packer.spec.ts +++ b/src/export/packer/packer.spec.ts @@ -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", () => { diff --git a/src/file/content-types/content-types.spec.ts b/src/file/content-types/content-types.spec.ts index 7e9b62c88f..e3cd62b984 100644 --- a/src/file/content-types/content-types.spec.ts +++ b/src/file/content-types/content-types.spec.ts @@ -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", () => { diff --git a/src/file/core-properties/properties.spec.ts b/src/file/core-properties/properties.spec.ts index 8edf920acb..92b2cd6139 100644 --- a/src/file/core-properties/properties.spec.ts +++ b/src/file/core-properties/properties.spec.ts @@ -1,6 +1,7 @@ import { expect } from "chai"; -import { Formatter } from "../../export/formatter"; +import { Formatter } from "export/formatter"; + import { CoreProperties } from "./properties"; describe("Properties", () => { diff --git a/src/file/document/body/body.spec.ts b/src/file/document/body/body.spec.ts index 67b9d9ab21..9ba95f33d0 100644 --- a/src/file/document/body/body.spec.ts +++ b/src/file/document/body/body.spec.ts @@ -1,6 +1,7 @@ import { expect } from "chai"; -import { Formatter } from "../../../export/formatter"; +import { Formatter } from "export/formatter"; + import { Body } from "./body"; describe("Body", () => { diff --git a/src/file/document/body/section-properties/page-border/page-borders.spec.ts b/src/file/document/body/section-properties/page-border/page-borders.spec.ts index 0bf22633ee..3ac11c1114 100644 --- a/src/file/document/body/section-properties/page-border/page-borders.spec.ts +++ b/src/file/document/body/section-properties/page-border/page-borders.spec.ts @@ -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", () => { diff --git a/src/file/document/body/section-properties/page-border/page-borders.ts b/src/file/document/body/section-properties/page-border/page-borders.ts index 4017fbb7ae..07aa4eabf1 100644 --- a/src/file/document/body/section-properties/page-border/page-borders.ts +++ b/src/file/document/body/section-properties/page-border/page-borders.ts @@ -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", diff --git a/src/file/document/body/section-properties/page-size/page-size.spec.ts b/src/file/document/body/section-properties/page-size/page-size.spec.ts index bd5b17aaa5..a99c3d2ed8 100644 --- a/src/file/document/body/section-properties/page-size/page-size.spec.ts +++ b/src/file/document/body/section-properties/page-size/page-size.spec.ts @@ -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"; diff --git a/src/file/document/body/section-properties/section-properties.spec.ts b/src/file/document/body/section-properties/section-properties.spec.ts index 9ab0621ad9..d767744e34 100644 --- a/src/file/document/body/section-properties/section-properties.spec.ts +++ b/src/file/document/body/section-properties/section-properties.spec.ts @@ -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, diff --git a/src/file/document/body/section-properties/section-properties.ts b/src/file/document/body/section-properties/section-properties.ts index ec8a6b6746..4a5fed5231 100644 --- a/src/file/document/body/section-properties/section-properties.ts +++ b/src/file/document/body/section-properties/section-properties.ts @@ -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"; diff --git a/src/file/document/body/section-properties/title-page/title-page.spec.ts b/src/file/document/body/section-properties/title-page/title-page.spec.ts index 75374a22db..3b89c974c4 100644 --- a/src/file/document/body/section-properties/title-page/title-page.spec.ts +++ b/src/file/document/body/section-properties/title-page/title-page.spec.ts @@ -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", () => { diff --git a/src/file/document/document.spec.ts b/src/file/document/document.spec.ts index e2e8781d7a..16c3b29f95 100644 --- a/src/file/document/document.spec.ts +++ b/src/file/document/document.spec.ts @@ -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"; diff --git a/src/file/drawing/anchor/anchor.spec.ts b/src/file/drawing/anchor/anchor.spec.ts index 58adefd174..cf93b19f7b 100644 --- a/src/file/drawing/anchor/anchor.spec.ts +++ b/src/file/drawing/anchor/anchor.spec.ts @@ -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( diff --git a/src/file/drawing/drawing.spec.ts b/src/file/drawing/drawing.spec.ts index 87ea5e9e44..6cf3761af8 100644 --- a/src/file/drawing/drawing.spec.ts +++ b/src/file/drawing/drawing.spec.ts @@ -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 = `iVBORw0KGgoAAAANSUhEUgAAAIAAAACACAMAAAD04JH5AAACzVBMVEUAAAAAAAAAAAAAAAA/AD8zMzMqKiokJCQfHx8cHBwZGRkuFxcqFSonJyckJCQiIiIfHx8eHh4cHBwoGhomGSYkJCQhISEfHx8eHh4nHR0lHBwkGyQjIyMiIiIgICAfHx8mHh4lHh4kHR0jHCMiGyIhISEgICAfHx8lHx8kHh4jHR0hHCEhISEgICAlHx8kHx8jHh4jHh4iHSIhHCEhISElICAkHx8jHx8jHh4iHh4iHSIhHSElICAkICAjHx8jHx8iHh4iHh4hHiEhHSEkICAjHx8iHx8iHx8hHh4hHiEkHSEjHSAjHx8iHx8iHx8hHh4kHiEkHiEjHSAiHx8hHx8hHh4kHiEjHiAjHSAiHx8iHx8hHx8kHh4jHiEjHiAjHiAiICAiHx8kHx8jHh4jHiEjHiAiHiAiHSAiHx8jHx8jHx8jHiAiHiAiHiAiHSAiHx8jHx8jHx8iHiAiHiAiHiAjHx8jHx8jHx8jHx8iHiAiHiAiHiAjHx8jHx8jHx8iHx8iHSAiHiAjHiAjHx8jHx8hHx8iHx8iHyAiHiAjHiAjHiAjHh4hHx8iHx8iHx8iHyAjHSAjHiAjHiAjHh4hHx8iHx8iHx8jHyAjHiAhHh4iHx8iHx8jHyAjHSAjHSAhHiAhHh4iHx8iHx8jHx8jHyAjHSAjHSAiHh4iHh4jHx8jHx8jHyAjHyAhHSAhHSAiHh4iHh4jHx8jHx8jHyAhHyAhHSAiHSAiHh4jHh4jHx8jHx8jHyAhHyAhHSAiHSAjHR4jHh4jHx8jHx8hHyAhHyAiHSAjHSAjHR4jHh4jHx8hHx8hHyAhHyAiHyAjHSAjHR4jHR4hHh4hHx8hHyAiHyAjHyAjHSAjHR4jHR4hHh4hHx8hHyAjHyAjHyAjHSAjHR4hHR4hHR4hHx8iHyAjHyAjHyAjHSAhHR4hHR4hHR4hHx8jHyAjHyAjHyAjHyC9S2xeAAAA7nRSTlMAAQIDBAUGBwgJCgsMDQ4PEBESExQVFxgZGhscHR4fICEiIyQlJicoKSorLS4vMDEyMzQ1Njc4OTo7PD0+P0BBQkNERUZISUpLTE1OUFFSU1RVVllaW1xdXmBhYmNkZWZnaGprbG1ub3Byc3R1dnd4eXp8fn+AgYKDhIWGiImKi4yNj5CRkpOUlZaXmJmam5ydnp+goaKjpKaoqqusra6vsLGys7S1tri5uru8vb6/wMHCw8TFxsfIycrLzM3Oz9DR0tPU1dbX2Nna29zd3t/g4eLj5OXm5+jp6uvs7e7v8PHy8/T19vf4+fr7/P3+fkZpVQAABcBJREFUGBntwftjlQMcBvDnnLNL22qzJjWlKLHFVogyty3SiFq6EZliqZGyhnSxsLlMRahYoZKRFcul5dKFCatYqWZaNKvWtrPz/A2+7/b27qRzec/lPfvl/XxgMplMJpPJZDKZAtA9HJ3ppnIez0KnSdtC0RCNznHdJrbrh85wdSlVVRaEXuoGamYi5K5430HNiTiEWHKJg05eRWgNfKeV7RxbqUhGKPV/207VupQ8is0IoX5vtFC18SqEHaK4GyHTZ2kzVR8PBTCO4oANIZL4ShNVZcOhKKeYg9DoWdhI1ec3os2VFI0JCIUez5+i6st0qJZRrEAIJCw+QdW223BG/EmKwTBc/IJ/qfp2FDrkUnwFo8U9dZyqnaPhxLqfYjyM1S3vb6p+GGOBszsojoTDSDFz6qj66R4LzvYJxVMwUNRjf1H1ywQr/megg2RzLximy8waqvbda8M5iijegVEiHjlM1W/3h+FcXesphsMY4dMOUnUgOxyuPEzxPQwRNvV3qg5Nj4BreyimwADWe/dRVTMjEm6MoGLzGwtystL6RyOY3qSqdlYU3FpLZw1VW0sK5943MvUCKwJ1noNtjs6Ohge76Zq9ZkfpigU5WWkDYuCfbs1U5HWFR8/Qq4a9W0uK5k4ZmdrTCl8spGIePLPlbqqsc1Afe83O0hULc8alDYiBd7ZyitYMeBfR55rR2fOKP6ioPk2dGvZ+UVI0d8rtqT2tcCexlqK2F3wRn5Q+YVbBqrLKOupkr9lZujAOrmS0UpTb4JeIPkNHZ+cXr6uoPk2vyuBSPhWLEKj45PQJuQWryyqP0Z14uGLdROHIRNBEXDR09EP5r62rOHCazhrD4VKPwxTH+sIA3ZPTJ+YuWV22n+IruHFDC8X2CBjnPoolcGc2FYUwzmsUWXDHsoGKLBhmN0VvuBVfTVE/AAbpaid5CB4MbaLY1QXGuIViLTyZQcVyGGMuxWPwaA0Vk2GI9RRp8Ci2iuLkIBjhT5LNUfAspZFiTwyC72KK7+DNg1SsRvCNp3gZXq2k4iEEXSHFJHgVXUlxejCCbTvFAHiXdIJiXxyCK7KJ5FHoMZGK9xBcwyg2QpdlVMxEUM2iyIMuXXZQNF+HswxMsSAAJRQjoE//eoqDCXBSTO6f1xd+O0iyNRY6jaWi1ALNYCocZROj4JdEikroVkjFk9DcStXxpdfCD2MoXodu4RUU9ptxxmXssOfxnvDVcxRTod9FxyhqLoAqis5aPhwTDp9spRgEH2Q6KLbYoKqlaKTm6Isp0C/sJMnjFvhiERXPQvUNRe9p29lhR04CdBpC8Sl8YiuncIxEuzUUg4Dkgj+paVozygY9plPMh28SaymO9kabAopREGF3vt9MzeFFl8G7lRSZ8FFGK8XX4VA8QjEd7XrM3M0OXz8YCy+qKBLgq3wqnofiTorF0Ax56Rg1J1elW+BBAsVe+My6iYq7IK6keBdOIseV2qn5Pb8f3MqkWAXf9ThM8c8lAOIotuFsF875lRrH5klRcG0+xcPwQ1oLxfeRAP4heQTnGL78X2rqlw2DK59SXAV/zKaiGMAuko5InCt68mcOan5+ohf+z1pP8lQY/GHZQMV4YD3FpXDp4qerqbF/lBWBswyi+AL+ia+maLgcRRQj4IYlY/UpauqKBsPJAxQF8NM1TRQ/RudSPAD34rK3scOuR8/HGcspxsJfOVS8NZbiGXiUtPgINU3v3WFDmx8pEuG3EiqKKVbCC1vm2iZqap5LAtCtleQf8F9sFYWDohzeJczYyQ4V2bEZFGsQgJRGqqqhS2phHTWn9lDkIhBTqWqxQZ+IsRvtdHY9AvI2VX2hW68nfqGmuQsCEl3JdjfCF8OW1bPdtwhQ0gm2mQzfRE3a7KCYj0BNZJs8+Kxf/r6WtTEI2FIqlsMfFgRB5A6KUnSe/vUkX0AnuvUIt8SjM1m6wWQymUwmk8lkMgXRf5vi8rLQxtUhAAAAAElFTkSuQmCC`; diff --git a/src/file/drawing/extent/extent.ts b/src/file/drawing/extent/extent.ts index 270a85a8a8..500571425b 100644 --- a/src/file/drawing/extent/extent.ts +++ b/src/file/drawing/extent/extent.ts @@ -1,4 +1,5 @@ import { XmlComponent } from "file/xml-components"; + import { ExtentAttributes } from "./extent-attributes"; export class Extent extends XmlComponent { diff --git a/src/file/drawing/floating/align.spec.ts b/src/file/drawing/floating/align.spec.ts index 5ec77d6fd0..a44ab7039b 100644 --- a/src/file/drawing/floating/align.spec.ts +++ b/src/file/drawing/floating/align.spec.ts @@ -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()", () => { diff --git a/src/file/drawing/floating/horizontal-position.spec.ts b/src/file/drawing/floating/horizontal-position.spec.ts index 1b139b47be..e04434e340 100644 --- a/src/file/drawing/floating/horizontal-position.spec.ts +++ b/src/file/drawing/floating/horizontal-position.spec.ts @@ -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", () => { diff --git a/src/file/drawing/floating/position-offset.spec.ts b/src/file/drawing/floating/position-offset.spec.ts index 74aebaebc2..237490f9f2 100644 --- a/src/file/drawing/floating/position-offset.spec.ts +++ b/src/file/drawing/floating/position-offset.spec.ts @@ -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", () => { diff --git a/src/file/drawing/floating/simple-pos.spec.ts b/src/file/drawing/floating/simple-pos.spec.ts index 5eee49f4c1..32218b7a33 100644 --- a/src/file/drawing/floating/simple-pos.spec.ts +++ b/src/file/drawing/floating/simple-pos.spec.ts @@ -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", () => { diff --git a/src/file/drawing/floating/vertical-position.spec.ts b/src/file/drawing/floating/vertical-position.spec.ts index a9d7ed65f8..42d70d7112 100644 --- a/src/file/drawing/floating/vertical-position.spec.ts +++ b/src/file/drawing/floating/vertical-position.spec.ts @@ -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", () => { diff --git a/src/file/file.ts b/src/file/file.ts index fd2b5746b7..e18b536490 100644 --- a/src/file/file.ts +++ b/src/file/file.ts @@ -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; } diff --git a/src/file/footer-wrapper.ts b/src/file/footer-wrapper.ts index 785f2724e4..2c51cf5072 100644 --- a/src/file/footer-wrapper.ts +++ b/src/file/footer-wrapper.ts @@ -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))); } diff --git a/src/file/footnotes/footnote/footnote.spec.ts b/src/file/footnotes/footnote/footnote.spec.ts index caeb8cc694..2db4fd094b 100644 --- a/src/file/footnotes/footnote/footnote.spec.ts +++ b/src/file/footnotes/footnote/footnote.spec.ts @@ -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", () => { diff --git a/src/file/footnotes/footnote/footnote.ts b/src/file/footnotes/footnote/footnote.ts index 6760e9bb03..0567695c40 100644 --- a/src/file/footnotes/footnote/footnote.ts +++ b/src/file/footnotes/footnote/footnote.ts @@ -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"; diff --git a/src/file/header-wrapper.ts b/src/file/header-wrapper.ts index beb7903cf5..f4a403ce27 100644 --- a/src/file/header-wrapper.ts +++ b/src/file/header-wrapper.ts @@ -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))); } diff --git a/src/file/media/media.ts b/src/file/media/media.ts index 284ca8806d..fdeb21b931 100644 --- a/src/file/media/media.ts +++ b/src/file/media/media.ts @@ -87,7 +87,7 @@ export class Media { } const imageData = { - referenceId: this.map.size + relationshipsCount + 1, + referenceId: relationshipsCount, stream: data, path: filePath, fileName: key, diff --git a/src/file/numbering/numbering.spec.ts b/src/file/numbering/numbering.spec.ts index 05dc4a391a..d27665a96e 100644 --- a/src/file/numbering/numbering.spec.ts +++ b/src/file/numbering/numbering.spec.ts @@ -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; diff --git a/src/file/paragraph/formatting/border.spec.ts b/src/file/paragraph/formatting/border.spec.ts index c86af41154..d0fda56359 100644 --- a/src/file/paragraph/formatting/border.spec.ts +++ b/src/file/paragraph/formatting/border.spec.ts @@ -1,6 +1,7 @@ import { assert } from "chai"; -import { Utility } from "../../../tests/utility"; +import { Utility } from "tests/utility"; + import { ThematicBreak } from "./border"; describe("Border", () => { diff --git a/src/file/paragraph/formatting/page-break.spec.ts b/src/file/paragraph/formatting/page-break.spec.ts index 6ba877311f..9412da322b 100644 --- a/src/file/paragraph/formatting/page-break.spec.ts +++ b/src/file/paragraph/formatting/page-break.spec.ts @@ -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", () => { diff --git a/src/file/paragraph/formatting/spacing.spec.ts b/src/file/paragraph/formatting/spacing.spec.ts index b8306ab821..b6ba808866 100644 --- a/src/file/paragraph/formatting/spacing.spec.ts +++ b/src/file/paragraph/formatting/spacing.spec.ts @@ -1,6 +1,7 @@ import { expect } from "chai"; -import { Formatter } from "../../../export/formatter"; +import { Formatter } from "export/formatter"; + import { Spacing } from "./spacing"; describe("Spacing", () => { diff --git a/src/file/paragraph/formatting/style.spec.ts b/src/file/paragraph/formatting/style.spec.ts index 118df1175c..bf70dc35a4 100644 --- a/src/file/paragraph/formatting/style.spec.ts +++ b/src/file/paragraph/formatting/style.spec.ts @@ -1,6 +1,7 @@ import { assert } from "chai"; -import { Utility } from "../../../tests/utility"; +import { Utility } from "tests/utility"; + import { Style } from "./style"; describe("ParagraphStyle", () => { diff --git a/src/file/paragraph/formatting/tab-stop.spec.ts b/src/file/paragraph/formatting/tab-stop.spec.ts index 5b324623f5..0b048bef98 100644 --- a/src/file/paragraph/formatting/tab-stop.spec.ts +++ b/src/file/paragraph/formatting/tab-stop.spec.ts @@ -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", () => { diff --git a/src/file/paragraph/formatting/unordered-list.spec.ts b/src/file/paragraph/formatting/unordered-list.spec.ts index c0fc274da0..38b65c1ded 100644 --- a/src/file/paragraph/formatting/unordered-list.spec.ts +++ b/src/file/paragraph/formatting/unordered-list.spec.ts @@ -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", () => { diff --git a/src/file/paragraph/image.spec.ts b/src/file/paragraph/image.spec.ts index 45c06b0628..c8289325e5 100644 --- a/src/file/paragraph/image.spec.ts +++ b/src/file/paragraph/image.spec.ts @@ -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", () => { diff --git a/src/file/paragraph/links/bookmark.spec.ts b/src/file/paragraph/links/bookmark.spec.ts index 08d0aec91c..a597347013 100644 --- a/src/file/paragraph/links/bookmark.spec.ts +++ b/src/file/paragraph/links/bookmark.spec.ts @@ -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; diff --git a/src/file/paragraph/links/hyperlink.spec.ts b/src/file/paragraph/links/hyperlink.spec.ts index d6432b432a..34c7d7dc7c 100644 --- a/src/file/paragraph/links/hyperlink.spec.ts +++ b/src/file/paragraph/links/hyperlink.spec.ts @@ -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", () => { diff --git a/src/file/paragraph/paragraph.spec.ts b/src/file/paragraph/paragraph.spec.ts index 2413769b1e..cafe231325 100644 --- a/src/file/paragraph/paragraph.spec.ts +++ b/src/file/paragraph/paragraph.spec.ts @@ -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", () => { diff --git a/src/file/paragraph/run/break.spec.ts b/src/file/paragraph/run/break.spec.ts index 2a317dd8b2..a07e1426bd 100644 --- a/src/file/paragraph/run/break.spec.ts +++ b/src/file/paragraph/run/break.spec.ts @@ -1,6 +1,7 @@ import { assert } from "chai"; -import { Utility } from "../../../tests/utility"; +import { Utility } from "tests/utility"; + import { Break } from "./break"; describe("Break", () => { diff --git a/src/file/paragraph/run/run-components/text.spec.ts b/src/file/paragraph/run/run-components/text.spec.ts index 02bd2c702d..49ec73f48b 100644 --- a/src/file/paragraph/run/run-components/text.spec.ts +++ b/src/file/paragraph/run/run-components/text.spec.ts @@ -1,6 +1,7 @@ import { expect } from "chai"; -import { Formatter } from "../../../../export/formatter"; +import { Formatter } from "export/formatter"; + import { Text } from "./text"; describe("Text", () => { diff --git a/src/file/paragraph/run/run-fonts.spec.ts b/src/file/paragraph/run/run-fonts.spec.ts index 366c0e16d5..af766e9f74 100644 --- a/src/file/paragraph/run/run-fonts.spec.ts +++ b/src/file/paragraph/run/run-fonts.spec.ts @@ -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", () => { diff --git a/src/file/paragraph/run/run.spec.ts b/src/file/paragraph/run/run.spec.ts index cdd925d9d5..c4ff3e8b70 100644 --- a/src/file/paragraph/run/run.spec.ts +++ b/src/file/paragraph/run/run.spec.ts @@ -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", () => { diff --git a/src/file/paragraph/run/script.spec.ts b/src/file/paragraph/run/script.spec.ts index df3d6fa01a..7d7a8cb1da 100644 --- a/src/file/paragraph/run/script.spec.ts +++ b/src/file/paragraph/run/script.spec.ts @@ -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", () => { diff --git a/src/file/paragraph/run/sequential-identifier.spec.ts b/src/file/paragraph/run/sequential-identifier.spec.ts index 1b34997b9c..f0f12cf8a8 100644 --- a/src/file/paragraph/run/sequential-identifier.spec.ts +++ b/src/file/paragraph/run/sequential-identifier.spec.ts @@ -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", () => { diff --git a/src/file/paragraph/run/strike.spec.ts b/src/file/paragraph/run/strike.spec.ts index 4e266da540..3d4f83db43 100644 --- a/src/file/paragraph/run/strike.spec.ts +++ b/src/file/paragraph/run/strike.spec.ts @@ -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", () => { diff --git a/src/file/paragraph/run/tab.spec.ts b/src/file/paragraph/run/tab.spec.ts index 4ae84e5f2b..600b4778ac 100644 --- a/src/file/paragraph/run/tab.spec.ts +++ b/src/file/paragraph/run/tab.spec.ts @@ -1,6 +1,7 @@ import { assert } from "chai"; -import { Utility } from "../../../tests/utility"; +import { Utility } from "tests/utility"; + import { Tab } from "./tab"; describe("Tab", () => { diff --git a/src/file/paragraph/run/text-run.spec.ts b/src/file/paragraph/run/text-run.spec.ts index 2ed219631d..817e030856 100644 --- a/src/file/paragraph/run/text-run.spec.ts +++ b/src/file/paragraph/run/text-run.spec.ts @@ -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", () => { diff --git a/src/file/paragraph/run/underline.spec.ts b/src/file/paragraph/run/underline.spec.ts index c9943bb5c5..c17efe54a2 100644 --- a/src/file/paragraph/run/underline.spec.ts +++ b/src/file/paragraph/run/underline.spec.ts @@ -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", () => { diff --git a/src/file/relationships/relationships.spec.ts b/src/file/relationships/relationships.spec.ts index 56cbead788..00ab8c25bb 100644 --- a/src/file/relationships/relationships.spec.ts +++ b/src/file/relationships/relationships.spec.ts @@ -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", () => { diff --git a/src/file/settings/settings.spec.ts b/src/file/settings/settings.spec.ts index 9ba0016319..9994be6686 100644 --- a/src/file/settings/settings.spec.ts +++ b/src/file/settings/settings.spec.ts @@ -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", () => { diff --git a/src/file/settings/update-fields.spec.ts b/src/file/settings/update-fields.spec.ts index 70fad8685c..90d409ac40 100644 --- a/src/file/settings/update-fields.spec.ts +++ b/src/file/settings/update-fields.spec.ts @@ -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": [ { diff --git a/src/file/styles/defaults/paragraph-properties.ts b/src/file/styles/defaults/paragraph-properties.ts index 536ba316ab..1ab3b623d6 100644 --- a/src/file/styles/defaults/paragraph-properties.ts +++ b/src/file/styles/defaults/paragraph-properties.ts @@ -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() { diff --git a/src/file/styles/defaults/run-properties.ts b/src/file/styles/defaults/run-properties.ts index 9f30986b84..1ab8f5752c 100644 --- a/src/file/styles/defaults/run-properties.ts +++ b/src/file/styles/defaults/run-properties.ts @@ -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; diff --git a/src/file/styles/index.ts b/src/file/styles/index.ts index d6cdbfc6f9..737bec0771 100644 --- a/src/file/styles/index.ts +++ b/src/file/styles/index.ts @@ -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"; diff --git a/src/file/styles/style/index.ts b/src/file/styles/style/index.ts index ee2d6d84aa..f262a473fb 100644 --- a/src/file/styles/style/index.ts +++ b/src/file/styles/style/index.ts @@ -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"; diff --git a/src/file/styles/styles.spec.ts b/src/file/styles/styles.spec.ts index 6262b3cb9e..8b7a8f793f 100644 --- a/src/file/styles/styles.spec.ts +++ b/src/file/styles/styles.spec.ts @@ -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; diff --git a/src/file/styles/styles.ts b/src/file/styles/styles.ts new file mode 100644 index 0000000000..d6cdbfc6f9 --- /dev/null +++ b/src/file/styles/styles.ts @@ -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; + } +} diff --git a/src/file/table-of-contents/field-instruction.ts b/src/file/table-of-contents/field-instruction.ts index 7194cf3f16..09f5129613 100644 --- a/src/file/table-of-contents/field-instruction.ts +++ b/src/file/table-of-contents/field-instruction.ts @@ -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) { diff --git a/src/file/table-of-contents/table-of-contents.spec.ts b/src/file/table-of-contents/table-of-contents.spec.ts index 6729f004ba..02a4c9c877 100644 --- a/src/file/table-of-contents/table-of-contents.spec.ts +++ b/src/file/table-of-contents/table-of-contents.spec.ts @@ -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', ], }, { diff --git a/src/file/table/grid.spec.ts b/src/file/table/grid.spec.ts index d8ace5ccef..75489f9bd9 100644 --- a/src/file/table/grid.spec.ts +++ b/src/file/table/grid.spec.ts @@ -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", () => { diff --git a/src/file/table/index.ts b/src/file/table/index.ts index dfba175857..a7adf3017e 100644 --- a/src/file/table/index.ts +++ b/src/file/table/index.ts @@ -1,2 +1,3 @@ export * from "./table"; export * from "./table-cell"; +export * from "./table-properties"; diff --git a/src/file/table/properties.ts b/src/file/table/properties.ts deleted file mode 100644 index 91ef393df3..0000000000 --- a/src/file/table/properties.ts +++ /dev/null @@ -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 { - 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", - }; -} diff --git a/src/file/table/table-cell/index.ts b/src/file/table/table-cell/index.ts new file mode 100644 index 0000000000..5a095cd19d --- /dev/null +++ b/src/file/table/table-cell/index.ts @@ -0,0 +1,2 @@ +export * from "./table-cell"; +export * from "./table-cell-components"; diff --git a/src/file/table/table-cell.ts b/src/file/table/table-cell/table-cell-components.ts similarity index 99% rename from src/file/table/table-cell.ts rename to src/file/table/table-cell/table-cell-components.ts index 046cc8d8aa..a81a66b3ae 100644 --- a/src/file/table/table-cell.ts +++ b/src/file/table/table-cell/table-cell-components.ts @@ -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; diff --git a/src/file/table/table-cell/table-cell-properties.ts b/src/file/table/table-cell/table-cell-properties.ts new file mode 100644 index 0000000000..639541d4cd --- /dev/null +++ b/src/file/table/table-cell/table-cell-properties.ts @@ -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; + } +} diff --git a/src/file/table/table-cell.spec.ts b/src/file/table/table-cell/table-cell.spec.ts similarity index 98% rename from src/file/table/table-cell.spec.ts rename to src/file/table/table-cell/table-cell.spec.ts index 4e761d2e07..a83b5812ad 100644 --- a/src/file/table/table-cell.spec.ts +++ b/src/file/table/table-cell/table-cell.spec.ts @@ -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", () => { diff --git a/src/file/table/table-cell/table-cell.ts b/src/file/table/table-cell/table-cell.ts new file mode 100644 index 0000000000..60673ec87a --- /dev/null +++ b/src/file/table/table-cell/table-cell.ts @@ -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; + } +} diff --git a/src/file/table/table-properties/index.ts b/src/file/table/table-properties/index.ts new file mode 100644 index 0000000000..913c3a7839 --- /dev/null +++ b/src/file/table/table-properties/index.ts @@ -0,0 +1,2 @@ +export * from "./table-properties"; +export * from "./table-float-properties"; diff --git a/src/file/table/table-properties/table-borders.ts b/src/file/table/table-properties/table-borders.ts new file mode 100644 index 0000000000..c27155ecd0 --- /dev/null +++ b/src/file/table/table-properties/table-borders.ts @@ -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", + }; +} diff --git a/src/file/table/table-cell-margin.ts b/src/file/table/table-properties/table-cell-margin.ts similarity index 97% rename from src/file/table/table-cell-margin.ts rename to src/file/table/table-properties/table-cell-margin.ts index 2b8fd32049..2cd14682fc 100644 --- a/src/file/table/table-cell-margin.ts +++ b/src/file/table/table-properties/table-cell-margin.ts @@ -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" }; diff --git a/src/file/table/table-properties/table-float-properties.spec.ts b/src/file/table/table-properties/table-float-properties.spec.ts new file mode 100644 index 0000000000..e527f5504a --- /dev/null +++ b/src/file/table/table-properties/table-float-properties.spec.ts @@ -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, + }, + }, + ], +}; diff --git a/src/file/table/table-properties/table-float-properties.ts b/src/file/table/table-properties/table-float-properties.ts new file mode 100644 index 0000000000..ae68df2b28 --- /dev/null +++ b/src/file/table/table-properties/table-float-properties.ts @@ -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 { + 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)); + } +} diff --git a/src/file/table/table-properties/table-layout.ts b/src/file/table/table-properties/table-layout.ts new file mode 100644 index 0000000000..85334181e0 --- /dev/null +++ b/src/file/table/table-properties/table-layout.ts @@ -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 })); + } +} diff --git a/src/file/table/properties.spec.ts b/src/file/table/table-properties/table-properties.spec.ts similarity index 91% rename from src/file/table/properties.spec.ts rename to src/file/table/table-properties/table-properties.spec.ts index a26e3fd352..1ffa43e6ff 100644 --- a/src/file/table/properties.spec.ts +++ b/src/file/table/table-properties/table-properties.spec.ts @@ -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", () => { diff --git a/src/file/table/table-properties/table-properties.ts b/src/file/table/table-properties/table-properties.ts new file mode 100644 index 0000000000..f8198eea59 --- /dev/null +++ b/src/file/table/table-properties/table-properties.ts @@ -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; + } +} diff --git a/src/file/table/table-properties/table-width.ts b/src/file/table/table-properties/table-width.ts new file mode 100644 index 0000000000..27caa5c819 --- /dev/null +++ b/src/file/table/table-properties/table-width.ts @@ -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 { + 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 })); + } +} diff --git a/src/file/table/table-row/index.ts b/src/file/table/table-row/index.ts new file mode 100644 index 0000000000..c8a880cf50 --- /dev/null +++ b/src/file/table/table-row/index.ts @@ -0,0 +1,2 @@ +export * from "./table-row"; +export * from "./table-row-properties"; diff --git a/src/file/table/table-row/table-row-properties.ts b/src/file/table/table-row/table-row-properties.ts new file mode 100644 index 0000000000..7d96ea9810 --- /dev/null +++ b/src/file/table/table-row/table-row-properties.ts @@ -0,0 +1,7 @@ +import { XmlComponent } from "file/xml-components"; + +export class TableRowProperties extends XmlComponent { + constructor() { + super("w:trPr"); + } +} diff --git a/src/file/table/table-row/table-row.ts b/src/file/table/table-row/table-row.ts new file mode 100644 index 0000000000..d1ced91c4a --- /dev/null +++ b/src/file/table/table-row/table-row.ts @@ -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); + } +} diff --git a/src/file/table/table.spec.ts b/src/file/table/table.spec.ts index 65871655b4..f1ddfe0ed6 100644 --- a/src/file/table/table.spec.ts +++ b/src/file/table/table.spec.ts @@ -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, + }, + }, + ], + }, + ], + }); + }); + }); }); diff --git a/src/file/table/table.ts b/src/file/table/table.ts index 3220bce537..8311b5ecfd 100644 --- a/src/file/table/table.ts +++ b/src/file/table/table.ts @@ -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; - } -} diff --git a/src/file/xml-components/xml-component.spec.ts b/src/file/xml-components/xml-component.spec.ts index 10e2f44dc4..ce198b135c 100644 --- a/src/file/xml-components/xml-component.spec.ts +++ b/src/file/xml-components/xml-component.spec.ts @@ -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 {} diff --git a/src/import-dotx/import-dotx.ts b/src/import-dotx/import-dotx.ts index b170f15aec..0b3ce692e2 100644 --- a/src/import-dotx/import-dotx.ts +++ b/src/import-dotx/import-dotx.ts @@ -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 { 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 { diff --git a/webpack.config.js b/webpack.config.js index 01ecff1540..40ec0b0d23 100644 --- a/webpack.config.js +++ b/webpack.config.js @@ -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/], + } ], },