diff --git a/.nycrc b/.nycrc index c521820b91..206058943b 100644 --- a/.nycrc +++ b/.nycrc @@ -1,9 +1,9 @@ { "check-coverage": true, - "lines": 98.67, - "functions": 97.08, - "branches": 95.6, - "statements": 98.68, + "lines": 98.79, + "functions": 97.54, + "branches": 95.64, + "statements": 98.8, "include": [ "src/**/*.ts" ], diff --git a/demo/11-declaritive-styles-2.ts b/demo/11-declaritive-styles-2.ts index 2f4ed78098..9c0ffa94c0 100644 --- a/demo/11-declaritive-styles-2.ts +++ b/demo/11-declaritive-styles-2.ts @@ -126,7 +126,14 @@ const doc = new Document({ }, }); -const image = Media.addImage(doc, fs.readFileSync("./demo/images/pizza.gif")); +const image = Media.addImage({ + document: doc, + data: fs.readFileSync("./demo/images/pizza.gif"), + transformation: { + width: 100, + height: 100, + }, +}); const table = new Table({ rows: [ @@ -161,8 +168,22 @@ const table = new Table({ ], }); -const image1 = Media.addImage(doc, fs.readFileSync("./demo/images/pizza.gif")); -const image2 = Media.addImage(doc, fs.readFileSync("./demo/images/pizza.gif")); +const image1 = Media.addImage({ + document: doc, + data: fs.readFileSync("./demo/images/pizza.gif"), + transformation: { + width: 100, + height: 100, + }, +}); +const image2 = Media.addImage({ + document: doc, + data: fs.readFileSync("./demo/images/pizza.gif"), + transformation: { + width: 100, + height: 100, + }, +}); doc.addSection({ properties: { diff --git a/demo/12-scaling-images.ts b/demo/12-scaling-images.ts index 6de5f49b92..f6876d29b8 100644 --- a/demo/12-scaling-images.ts +++ b/demo/12-scaling-images.ts @@ -5,10 +5,38 @@ import { Document, Media, Packer, Paragraph } from "../build"; const doc = new Document(); -const image = Media.addImage(doc, fs.readFileSync("./demo/images/pizza.gif"), 50, 50); -const image2 = Media.addImage(doc, fs.readFileSync("./demo/images/pizza.gif"), 100, 100); -const image3 = Media.addImage(doc, fs.readFileSync("./demo/images/pizza.gif"), 250, 250); -const image4 = Media.addImage(doc, fs.readFileSync("./demo/images/pizza.gif"), 400, 400); +const image = Media.addImage({ + document: doc, + data: fs.readFileSync("./demo/images/pizza.gif"), + transformation: { + width: 50, + height: 50, + }, +}); +const image2 = Media.addImage({ + document: doc, + data: fs.readFileSync("./demo/images/pizza.gif"), + transformation: { + width: 100, + height: 100, + }, +}); +const image3 = Media.addImage({ + document: doc, + data: fs.readFileSync("./demo/images/pizza.gif"), + transformation: { + width: 250, + height: 250, + }, +}); +const image4 = Media.addImage({ + document: doc, + data: fs.readFileSync("./demo/images/pizza.gif"), + transformation: { + width: 400, + height: 400, + }, +}); doc.addSection({ children: [new Paragraph("Hello World"), new Paragraph(image), new Paragraph(image2), new Paragraph(image3), new Paragraph(image4)], diff --git a/demo/18-image-from-buffer.ts b/demo/18-image-from-buffer.ts index 146b1b421f..72ba1c0257 100644 --- a/demo/18-image-from-buffer.ts +++ b/demo/18-image-from-buffer.ts @@ -7,7 +7,14 @@ const doc = new Document(); const imageBase64Data = `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`; -const image = Media.addImage(doc, Buffer.from(imageBase64Data, "base64"), 100, 100); +const image = Media.addImage({ + document: doc, + data: Buffer.from(imageBase64Data, "base64"), + transformation: { + width: 100, + height: 100, + }, +}); doc.addSection({ children: [ diff --git a/demo/23-base64-images.ts b/demo/23-base64-images.ts index c927ba45ef..91f48c6768 100644 --- a/demo/23-base64-images.ts +++ b/demo/23-base64-images.ts @@ -5,14 +5,56 @@ import { Document, Media, Packer, Paragraph, TextRun } from "../build"; const doc = new Document(); -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 image = Media.addImage({ + document: doc, + data: fs.readFileSync("./demo/images/image1.jpeg"), + transformation: { + width: 100, + height: 100, + }, +}); +const image2 = Media.addImage({ + document: doc, + data: fs.readFileSync("./demo/images/dog.png"), + transformation: { + width: 100, + height: 100, + }, +}); +const image3 = Media.addImage({ + document: doc, + data: fs.readFileSync("./demo/images/cat.jpg"), + transformation: { + width: 100, + height: 100, + }, +}); +const image4 = Media.addImage({ + document: doc, + data: fs.readFileSync("./demo/images/parrots.bmp"), + transformation: { + width: 100, + height: 100, + }, +}); +const image5 = Media.addImage({ + document: doc, + data: fs.readFileSync("./demo/images/pizza.gif"), + transformation: { + width: 100, + height: 100, + }, +}); const imageBase64Data = `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`; -const image6 = Media.addImage(doc, Buffer.from(imageBase64Data, "base64"), 100, 100); +const image6 = Media.addImage({ + document: doc, + data: Buffer.from(imageBase64Data, "base64"), + transformation: { + width: 100, + height: 100, + }, +}); doc.addSection({ children: [ diff --git a/demo/24-images-to-table-cell.ts b/demo/24-images-to-table-cell.ts index e37d1aa812..1d024a4c2d 100644 --- a/demo/24-images-to-table-cell.ts +++ b/demo/24-images-to-table-cell.ts @@ -5,7 +5,14 @@ import { Document, Media, Packer, Paragraph, Table, TableCell, TableRow } from " const doc = new Document(); -const image = Media.addImage(doc, fs.readFileSync("./demo/images/image1.jpeg")); +const image = Media.addImage({ + document: doc, + data: fs.readFileSync("./demo/images/image1.jpeg"), + transformation: { + width: 100, + height: 100, + }, +}); const table = new Table({ rows: [ diff --git a/demo/35-hyperlinks.ts b/demo/35-hyperlinks.ts index a350198113..44f183d687 100644 --- a/demo/35-hyperlinks.ts +++ b/demo/35-hyperlinks.ts @@ -24,7 +24,14 @@ const doc = new Document({ }, }); -const image1 = Media.addImage(doc, fs.readFileSync("./demo/images/image1.jpeg")); +const image1 = Media.addImage({ + document: doc, + data: fs.readFileSync("./demo/images/image1.jpeg"), + transformation: { + width: 100, + height: 100, + }, +}); doc.addSection({ footers: { diff --git a/demo/36-image-to-table-cell.ts b/demo/36-image-to-table-cell.ts index a0d87230a2..3a31d4d264 100644 --- a/demo/36-image-to-table-cell.ts +++ b/demo/36-image-to-table-cell.ts @@ -4,7 +4,14 @@ import * as fs from "fs"; import { Document, Header, Media, Packer, Paragraph, Table, TableCell, TableRow } from "../build"; const doc = new Document(); -const image = Media.addImage(doc, fs.readFileSync("./demo/images/image1.jpeg")); +const image = Media.addImage({ + document: doc, + data: fs.readFileSync("./demo/images/image1.jpeg"), + transformation: { + width: 100, + height: 100, + }, +}); const table = new Table({ rows: [ diff --git a/demo/37-images-to-header-and-footer.ts b/demo/37-images-to-header-and-footer.ts index 86a8a20218..f75385f7b5 100644 --- a/demo/37-images-to-header-and-footer.ts +++ b/demo/37-images-to-header-and-footer.ts @@ -4,9 +4,30 @@ import * as fs from "fs"; import { Document, Header, Media, Packer, Paragraph } from "../build"; const doc = new Document(); -const image = Media.addImage(doc, fs.readFileSync("./demo/images/image1.jpeg")); -const image1 = Media.addImage(doc, fs.readFileSync("./demo/images/pizza.gif")); -const image2 = Media.addImage(doc, fs.readFileSync("./demo/images/image1.jpeg")); +const image = Media.addImage({ + document: doc, + data: fs.readFileSync("./demo/images/image1.jpeg"), + transformation: { + width: 100, + height: 100, + }, +}); +const image1 = Media.addImage({ + document: doc, + data: fs.readFileSync("./demo/images/pizza.gif"), + transformation: { + width: 100, + height: 100, + }, +}); +const image2 = Media.addImage({ + document: doc, + data: fs.readFileSync("./demo/images/image1.jpeg"), + transformation: { + width: 100, + height: 100, + }, +}); doc.addSection({ headers: { diff --git a/demo/38-text-wrapping.ts b/demo/38-text-wrapping.ts index 9dac048e52..470365454e 100644 --- a/demo/38-text-wrapping.ts +++ b/demo/38-text-wrapping.ts @@ -6,7 +6,13 @@ import { Document, Media, Packer, Paragraph, TextWrappingSide, TextWrappingType const doc = new Document(); -const image = Media.addImage(doc, fs.readFileSync("./demo/images/pizza.gif"), 200, 200, { +const image = Media.addImage({ + document: doc, + data: fs.readFileSync("./demo/images/pizza.gif"), + transformation: { + width: 200, + height: 200, + }, floating: { horizontalPosition: { offset: 2014400, diff --git a/demo/5-images.ts b/demo/5-images.ts index 3c752d9a58..8509a23b80 100644 --- a/demo/5-images.ts +++ b/demo/5-images.ts @@ -15,12 +15,65 @@ import { const doc = new Document(); -const image1 = Media.addImage(doc, fs.readFileSync("./demo/images/image1.jpeg")); -const image2 = Media.addImage(doc, fs.readFileSync("./demo/images/dog.png").toString("base64")); -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 image6 = Media.addImage(doc, fs.readFileSync("./demo/images/pizza.gif"), 200, 200, { +const image1 = Media.addImage({ + document: doc, + data: fs.readFileSync("./demo/images/image1.jpeg"), + transformation: { + width: 100, + height: 100, + }, +}); +const image2 = Media.addImage({ + document: doc, + data: fs.readFileSync("./demo/images/dog.png").toString("base64"), + transformation: { + width: 100, + height: 100, + }, +}); +const image3 = Media.addImage({ + document: doc, + data: fs.readFileSync("./demo/images/cat.jpg"), + transformation: { + width: 100, + height: 100, + flip: { + vertical: true, + }, + }, +}); +const image4 = Media.addImage({ + document: doc, + data: fs.readFileSync("./demo/images/parrots.bmp"), + transformation: { + width: 150, + height: 150, + flip: { + horizontal: true, + }, + rotation: 225, + }, +}); +const image5 = Media.addImage({ + document: doc, + data: fs.readFileSync("./demo/images/pizza.gif"), + transformation: { + width: 200, + height: 200, + flip: { + horizontal: true, + vertical: true, + }, + }, +}); +const image6 = Media.addImage({ + document: doc, + data: fs.readFileSync("./demo/images/pizza.gif"), + transformation: { + width: 200, + height: 200, + rotation: 45, + }, floating: { zIndex: 10, horizontalPosition: { @@ -32,7 +85,13 @@ const image6 = Media.addImage(doc, fs.readFileSync("./demo/images/pizza.gif"), 2 }, }); -const image7 = Media.addImage(doc, fs.readFileSync("./demo/images/cat.jpg"), 200, 200, { +const image7 = Media.addImage({ + document: doc, + data: fs.readFileSync("./demo/images/cat.jpg"), + transformation: { + width: 200, + height: 200, + }, floating: { zIndex: 5, horizontalPosition: { diff --git a/demo/50-readme-demo.ts b/demo/50-readme-demo.ts index 6b1cc0ecab..9b69335fbe 100644 --- a/demo/50-readme-demo.ts +++ b/demo/50-readme-demo.ts @@ -5,8 +5,22 @@ import { Document, HeadingLevel, Media, Packer, Paragraph, Table, TableCell, Tab const doc = new Document(); -const image1 = Media.addImage(doc, fs.readFileSync("./demo/images/image1.jpeg")); -const image2 = Media.addImage(doc, fs.readFileSync("./demo/images/pizza.gif")); +const image1 = Media.addImage({ + document: doc, + data: fs.readFileSync("./demo/images/image1.jpeg"), + transformation: { + width: 100, + height: 100, + }, +}); +const image2 = Media.addImage({ + document: doc, + data: fs.readFileSync("./demo/images/pizza.gif"), + transformation: { + width: 100, + height: 100, + }, +}); const table = new Table({ rows: [ diff --git a/demo/9-images-in-header-and-footer.ts b/demo/9-images-in-header-and-footer.ts index 75acd4f07f..722d8f041d 100644 --- a/demo/9-images-in-header-and-footer.ts +++ b/demo/9-images-in-header-and-footer.ts @@ -5,8 +5,22 @@ import { Document, Footer, Header, Media, Packer, Paragraph } from "../build"; const doc = new Document(); -const image1 = Media.addImage(doc, fs.readFileSync("./demo/images/pizza.gif")); -const image2 = Media.addImage(doc, fs.readFileSync("./demo/images/pizza.gif")); +const image1 = Media.addImage({ + document: doc, + data: fs.readFileSync("./demo/images/pizza.gif"), + transformation: { + width: 100, + height: 100, + }, +}); +const image2 = Media.addImage({ + document: doc, + data: fs.readFileSync("./demo/images/pizza.gif"), + transformation: { + width: 100, + height: 100, + }, +}); doc.addSection({ headers: { diff --git a/docs/usage/images.md b/docs/usage/images.md index 94e75e75a7..99ba7ebd8c 100644 --- a/docs/usage/images.md +++ b/docs/usage/images.md @@ -5,7 +5,13 @@ To create a `floating` image on top of text: ```ts -Media.addImage(doc, fs.readFileSync("./demo/images/pizza.gif"), 200, 200, { +const image = Media.addImage({ + document: doc, + data: fs.readFileSync("./demo/images/pizza.gif"), + transformation: { + width: 200, + height: 200, + } floating: { horizontalPosition: { offset: 1014400, @@ -20,7 +26,14 @@ Media.addImage(doc, fs.readFileSync("./demo/images/pizza.gif"), 200, 200, { By default with no arguments, its an `inline` image: ```ts -const image = Media.addImage(doc, fs.readFileSync("./demo/images/pizza.gif")); +const image = Media.addImage({ + document: doc, + data: fs.readFileSync("./demo/images/pizza.gif"), + transformation: { + width: 100, + height: 100, + }, +}); ``` Add it into the document by adding the image into a paragraph: @@ -50,13 +63,21 @@ Adding images can be done in two ways: 1. Call the `createImage` method to add the image directly into the `document`: ```ts - Media.addImage(doc, [IMAGE_BUFFER], [WIDTH], [HEIGHT], [POSITION_OPTIONS]); + Media.addImage({}); ``` 2. Create an `image` first, then add it into the `document`: ```ts - const image = Media.addImage(doc, [IMAGE_BUFFER]); + const image = Media.addImage({ + document: doc, + data: [IMAGE_BUFFER], + transformation: { + width: [IMAGE_SIZE], + height: [IMAGE_SIZE], + }, + }); + doc.addSection({ children: [new Paragraph(image)], }); @@ -86,7 +107,13 @@ Pass `options` into the `[POSITION_OPTIONS]` metioned in the [Intro above](#Intr To change the position the image to be on top of the text, simply add the `floating` property to the last argument. By default, the offsets are relative to the top left corner of the `page`. Offset units are in [emus](https://startbigthinksmall.wordpress.com/2010/01/04/points-inches-and-emus-measuring-units-in-office-open-xml/): ```ts -const imageData = document.createImage(buffer, 903, 1149, { +const image = Media.addImage({ + document: doc, + data: buffer, + transformation: { + width: 903, + height: 1149, + }, floating: { horizontalPosition: { offset: 1014400, // relative: HorizontalPositionRelativeFrom.PAGE by default @@ -99,7 +126,13 @@ const imageData = document.createImage(buffer, 903, 1149, { ``` ```ts -const imageData = document.createImage(buffer, 903, 1149, { +const image = Media.addImage({ + document: doc, + data: buffer, + transformation: { + width: 903, + height: 1149, + }, floating: { horizontalPosition: { relative: HorizontalPositionRelativeFrom.RIGHT_MARGIN, @@ -159,7 +192,13 @@ wrap: { For example: ```ts -Media.addImage(doc, fs.readFileSync("./demo/images/pizza.gif"), 200, 200, { +Media.addImage({ + document: doc, + data: fs.readFileSync("./demo/images/pizza.gif"), + transformation: { + width: 200, + height: 200, + }, floating: { horizontalPosition: { offset: 2014400, @@ -202,7 +241,13 @@ margins: { For example: ```ts -Media.addImage(doc, fs.readFileSync("./demo/images/pizza.gif"), 200, 200, { +Media.addImage({ + document: doc, + data: fs.readFileSync("./demo/images/pizza.gif"), + transformation: { + width: 200, + height: 200, + }, floating: { horizontalPosition: { offset: 2014400, @@ -228,7 +273,7 @@ Media.addImage(doc, fs.readFileSync("./demo/images/pizza.gif"), 200, 200, { Importing Images from file system path -[Example](https://raw.githubusercontent.com/dolanmiu/docx/master/demo/5-images.ts ':include') +[Example](https://raw.githubusercontent.com/dolanmiu/docx/master/demo/5-images.ts ":include") _Source: https://github.com/dolanmiu/docx/blob/master/demo/5-images.ts_ @@ -236,7 +281,7 @@ _Source: https://github.com/dolanmiu/docx/blob/master/demo/5-images.ts_ Example showing how to add image to headers and footers -[Example](https://raw.githubusercontent.com/dolanmiu/docx/master/demo/9-images-in-header-and-footer.ts ':include') +[Example](https://raw.githubusercontent.com/dolanmiu/docx/master/demo/9-images-in-header-and-footer.ts ":include") _Source: https://github.com/dolanmiu/docx/blob/master/demo/9-images-in-header-and-footer.ts_ @@ -244,6 +289,6 @@ _Source: https://github.com/dolanmiu/docx/blob/master/demo/9-images-in-header-an Example showing how to float images on top of text and optimally give a `margin` -[Example](https://raw.githubusercontent.com/dolanmiu/docx/master/demo/38-text-wrapping.ts ':include') +[Example](https://raw.githubusercontent.com/dolanmiu/docx/master/demo/38-text-wrapping.ts ":include") _Source: https://github.com/dolanmiu/docx/blob/master/demo/38-text-wrapping.ts_ diff --git a/src/export/packer/image-replacer.spec.ts b/src/export/packer/image-replacer.spec.ts index a5f000c2df..0c503d9f4b 100644 --- a/src/export/packer/image-replacer.spec.ts +++ b/src/export/packer/image-replacer.spec.ts @@ -42,7 +42,7 @@ describe("ImageReplacer", () => { { stream: Buffer.from(""), fileName: "test-image.png", - dimensions: { + transformation: { pixels: { x: 100, y: 100, diff --git a/src/file/drawing/anchor/anchor.spec.ts b/src/file/drawing/anchor/anchor.spec.ts index 10d4b08d13..d9d0be1015 100644 --- a/src/file/drawing/anchor/anchor.spec.ts +++ b/src/file/drawing/anchor/anchor.spec.ts @@ -11,7 +11,7 @@ function createAnchor(drawingOptions: IDrawingOptions): Anchor { { fileName: "test.png", stream: new Buffer(""), - dimensions: { + transformation: { pixels: { x: 0, y: 0, diff --git a/src/file/drawing/anchor/anchor.ts b/src/file/drawing/anchor/anchor.ts index 7eb4487a89..3d2d906500 100644 --- a/src/file/drawing/anchor/anchor.ts +++ b/src/file/drawing/anchor/anchor.ts @@ -1,5 +1,5 @@ // http://officeopenxml.com/drwPicFloating.php -import { IMediaData, IMediaDataDimensions } from "file/media"; +import { IMediaData, IMediaDataTransformation } from "file/media"; import { XmlComponent } from "file/xml-components"; import { IDrawingOptions } from "../drawing"; import { HorizontalPosition, IFloating, SimplePos, VerticalPosition } from "../floating"; @@ -12,7 +12,7 @@ import { GraphicFrameProperties } from "./../graphic-frame/graphic-frame-propert import { AnchorAttributes } from "./anchor-attributes"; export class Anchor extends XmlComponent { - constructor(mediaData: IMediaData, dimensions: IMediaDataDimensions, drawingOptions: IDrawingOptions) { + constructor(mediaData: IMediaData, transform: IMediaDataTransformation, drawingOptions: IDrawingOptions) { super("wp:anchor"); const floating: IFloating = { @@ -36,14 +36,14 @@ export class Anchor extends XmlComponent { behindDoc: floating.behindDocument === true ? "1" : "0", locked: floating.lockAnchor === true ? "1" : "0", layoutInCell: floating.layoutInCell === true ? "1" : "0", - relativeHeight: floating.zIndex ? floating.zIndex : dimensions.emus.y, + relativeHeight: floating.zIndex ? floating.zIndex : transform.emus.y, }), ); this.root.push(new SimplePos()); this.root.push(new HorizontalPosition(floating.horizontalPosition)); this.root.push(new VerticalPosition(floating.verticalPosition)); - this.root.push(new Extent(dimensions.emus.x, dimensions.emus.y)); + this.root.push(new Extent(transform.emus.x, transform.emus.y)); this.root.push(new EffectExtent()); if (drawingOptions.floating !== undefined && drawingOptions.floating.wrap !== undefined) { @@ -67,6 +67,6 @@ export class Anchor extends XmlComponent { this.root.push(new DocProperties()); this.root.push(new GraphicFrameProperties()); - this.root.push(new Graphic(mediaData, dimensions.emus.x, dimensions.emus.y)); + this.root.push(new Graphic(mediaData, transform)); } } diff --git a/src/file/drawing/drawing.spec.ts b/src/file/drawing/drawing.spec.ts index 9ffda2add0..d23377e674 100644 --- a/src/file/drawing/drawing.spec.ts +++ b/src/file/drawing/drawing.spec.ts @@ -13,7 +13,7 @@ function createDrawing(drawingOptions?: IDrawingOptions): Drawing { fileName: "test.jpg", stream: Buffer.from(imageBase64Data, "base64"), path: path, - dimensions: { + transformation: { pixels: { x: 100, y: 100, @@ -165,6 +165,9 @@ describe("Drawing", () => { }, { "a:xfrm": [ + { + _attr: {}, + }, { "a:ext": { _attr: { @@ -392,6 +395,9 @@ describe("Drawing", () => { }, { "a:xfrm": [ + { + _attr: {}, + }, { "a:ext": { _attr: { diff --git a/src/file/drawing/drawing.ts b/src/file/drawing/drawing.ts index 3a331c7a47..d42f403cf2 100644 --- a/src/file/drawing/drawing.ts +++ b/src/file/drawing/drawing.ts @@ -22,10 +22,10 @@ export class Drawing extends XmlComponent { super("w:drawing"); if (!drawingOptions.floating) { - this.inline = new Inline(imageData, imageData.dimensions); + this.inline = new Inline(imageData, imageData.transformation); this.root.push(this.inline); } else { - this.root.push(new Anchor(imageData, imageData.dimensions, drawingOptions)); + this.root.push(new Anchor(imageData, imageData.transformation, drawingOptions)); } } diff --git a/src/file/drawing/inline/graphic/graphic-data/graphic-data.ts b/src/file/drawing/inline/graphic/graphic-data/graphic-data.ts index ce04f68179..9a4c9a32de 100644 --- a/src/file/drawing/inline/graphic/graphic-data/graphic-data.ts +++ b/src/file/drawing/inline/graphic/graphic-data/graphic-data.ts @@ -1,4 +1,4 @@ -import { IMediaData } from "file/media"; +import { IMediaData, IMediaDataTransformation } from "file/media"; import { XmlComponent } from "file/xml-components"; import { GraphicDataAttributes } from "./graphic-data-attribute"; @@ -7,7 +7,7 @@ import { Pic } from "./pic"; export class GraphicData extends XmlComponent { private readonly pic: Pic; - constructor(mediaData: IMediaData, x: number, y: number) { + constructor(mediaData: IMediaData, transform: IMediaDataTransformation) { super("a:graphicData"); this.root.push( @@ -16,7 +16,7 @@ export class GraphicData extends XmlComponent { }), ); - this.pic = new Pic(mediaData, x, y); + this.pic = new Pic(mediaData, transform); this.root.push(this.pic); } diff --git a/src/file/drawing/inline/graphic/graphic-data/pic/pic.ts b/src/file/drawing/inline/graphic/graphic-data/pic/pic.ts index cce8116677..280dd8796e 100644 --- a/src/file/drawing/inline/graphic/graphic-data/pic/pic.ts +++ b/src/file/drawing/inline/graphic/graphic-data/pic/pic.ts @@ -1,5 +1,5 @@ // http://officeopenxml.com/drwPic.php -import { IMediaData } from "file/media"; +import { IMediaData, IMediaDataTransformation } from "file/media"; import { XmlComponent } from "file/xml-components"; import { BlipFill } from "./blip/blip-fill"; @@ -10,7 +10,7 @@ import { ShapeProperties } from "./shape-properties/shape-properties"; export class Pic extends XmlComponent { private readonly shapeProperties: ShapeProperties; - constructor(mediaData: IMediaData, x: number, y: number) { + constructor(mediaData: IMediaData, transform: IMediaDataTransformation) { super("pic:pic"); this.root.push( @@ -19,11 +19,11 @@ export class Pic extends XmlComponent { }), ); - this.shapeProperties = new ShapeProperties(x, y); + this.shapeProperties = new ShapeProperties(transform); this.root.push(new NonVisualPicProperties()); this.root.push(new BlipFill(mediaData)); - this.root.push(new ShapeProperties(x, y)); + this.root.push(new ShapeProperties(transform)); } public setXY(x: number, y: number): void { diff --git a/src/file/drawing/inline/graphic/graphic-data/pic/shape-properties/form.spec.ts b/src/file/drawing/inline/graphic/graphic-data/pic/shape-properties/form.spec.ts new file mode 100644 index 0000000000..3d46b1875a --- /dev/null +++ b/src/file/drawing/inline/graphic/graphic-data/pic/shape-properties/form.spec.ts @@ -0,0 +1,93 @@ +import { expect } from "chai"; + +import { Formatter } from "export/formatter"; +import { Form } from "./form/form"; + +describe("Form", () => { + describe("#constructor()", () => { + it("should create", () => { + const tree = new Formatter().format( + new Form({ + pixels: { + x: 100, + y: 100, + }, + emus: { + x: 100, + y: 100, + }, + }), + ); + + expect(tree).to.deep.equal({ + "a:xfrm": [ + { + _attr: {}, + }, + { + "a:ext": { + _attr: { + cx: 100, + cy: 100, + }, + }, + }, + { + "a:off": { + _attr: { + x: 0, + y: 0, + }, + }, + }, + ], + }); + }); + + it("should create with flip", () => { + const tree = new Formatter().format( + new Form({ + pixels: { + x: 100, + y: 100, + }, + emus: { + x: 100, + y: 100, + }, + flip: { + vertical: true, + horizontal: true, + }, + }), + ); + + expect(tree).to.deep.equal({ + "a:xfrm": [ + { + _attr: { + flipH: true, + flipV: true, + }, + }, + { + "a:ext": { + _attr: { + cx: 100, + cy: 100, + }, + }, + }, + { + "a:off": { + _attr: { + x: 0, + y: 0, + }, + }, + }, + ], + }); + }); + }); +}); diff --git a/src/file/drawing/inline/graphic/graphic-data/pic/shape-properties/form/form.ts b/src/file/drawing/inline/graphic/graphic-data/pic/shape-properties/form/form.ts index 48c069f644..5311b83911 100644 --- a/src/file/drawing/inline/graphic/graphic-data/pic/shape-properties/form/form.ts +++ b/src/file/drawing/inline/graphic/graphic-data/pic/shape-properties/form/form.ts @@ -1,15 +1,38 @@ // http://officeopenxml.com/drwSp-size.php -import { XmlComponent } from "file/xml-components"; +// http://officeopenxml.com/drwSp-rotate.php +import { IMediaDataTransformation } from "file/media"; +import { XmlAttributeComponent, XmlComponent } from "file/xml-components"; + import { Extents } from "./extents/extents"; import { Offset } from "./offset/off"; +export class FormAttributes extends XmlAttributeComponent<{ + readonly flipVertical?: boolean; + readonly flipHorizontal?: boolean; + readonly rotation?: number; +}> { + protected readonly xmlKeys = { + flipVertical: "flipV", + flipHorizontal: "flipH", + rotation: "rot", + }; +} + export class Form extends XmlComponent { private readonly extents: Extents; - constructor(x: number, y: number) { + constructor(options: IMediaDataTransformation) { super("a:xfrm"); - this.extents = new Extents(x, y); + this.root.push( + new FormAttributes({ + flipVertical: options.flip?.vertical, + flipHorizontal: options.flip?.horizontal, + rotation: options.rotation, + }), + ); + + this.extents = new Extents(options.emus.x, options.emus.y); this.root.push(this.extents); this.root.push(new Offset()); diff --git a/src/file/drawing/inline/graphic/graphic-data/pic/shape-properties/no-fill.ts b/src/file/drawing/inline/graphic/graphic-data/pic/shape-properties/no-fill.ts deleted file mode 100644 index 4e847a1d56..0000000000 --- a/src/file/drawing/inline/graphic/graphic-data/pic/shape-properties/no-fill.ts +++ /dev/null @@ -1,7 +0,0 @@ -import { XmlComponent } from "file/xml-components"; - -export class NoFill extends XmlComponent { - constructor() { - super("a:noFill"); - } -} diff --git a/src/file/drawing/inline/graphic/graphic-data/pic/shape-properties/outline/no-fill.spec.ts b/src/file/drawing/inline/graphic/graphic-data/pic/shape-properties/outline/no-fill.spec.ts new file mode 100644 index 0000000000..e12ee1a3b9 --- /dev/null +++ b/src/file/drawing/inline/graphic/graphic-data/pic/shape-properties/outline/no-fill.spec.ts @@ -0,0 +1,16 @@ +import { expect } from "chai"; + +import { Formatter } from "export/formatter"; + +import { NoFill } from "./no-fill"; + +describe("NoFill", () => { + describe("#constructor()", () => { + it("should create", () => { + const tree = new Formatter().format(new NoFill()); + expect(tree).to.deep.equal({ + "a:noFill": {}, + }); + }); + }); +}); diff --git a/src/file/drawing/inline/graphic/graphic-data/pic/shape-properties/outline/outline.spec.ts b/src/file/drawing/inline/graphic/graphic-data/pic/shape-properties/outline/outline.spec.ts new file mode 100644 index 0000000000..732f74004b --- /dev/null +++ b/src/file/drawing/inline/graphic/graphic-data/pic/shape-properties/outline/outline.spec.ts @@ -0,0 +1,19 @@ +import { expect } from "chai"; + +import { Formatter } from "export/formatter"; +import { Outline } from "./outline"; + +describe("Outline", () => { + describe("#constructor()", () => { + it("should create", () => { + const tree = new Formatter().format(new Outline()); + expect(tree).to.deep.equal({ + "a:ln": [ + { + "a:noFill": {}, + }, + ], + }); + }); + }); +}); diff --git a/src/file/drawing/inline/graphic/graphic-data/pic/shape-properties/shape-properties.ts b/src/file/drawing/inline/graphic/graphic-data/pic/shape-properties/shape-properties.ts index 9dacae18d6..769e242205 100644 --- a/src/file/drawing/inline/graphic/graphic-data/pic/shape-properties/shape-properties.ts +++ b/src/file/drawing/inline/graphic/graphic-data/pic/shape-properties/shape-properties.ts @@ -1,4 +1,5 @@ // http://officeopenxml.com/drwSp-SpPr.php +import { IMediaDataTransformation } from "file/media"; import { XmlComponent } from "file/xml-components"; import { Form } from "./form"; // import { NoFill } from "./no-fill"; @@ -9,7 +10,7 @@ import { ShapePropertiesAttributes } from "./shape-properties-attributes"; export class ShapeProperties extends XmlComponent { private readonly form: Form; - constructor(x: number, y: number) { + constructor(transform: IMediaDataTransformation) { super("pic:spPr"); this.root.push( @@ -18,7 +19,7 @@ export class ShapeProperties extends XmlComponent { }), ); - this.form = new Form(x, y); + this.form = new Form(transform); this.root.push(this.form); this.root.push(new PresetGeometry()); diff --git a/src/file/drawing/inline/graphic/graphic.ts b/src/file/drawing/inline/graphic/graphic.ts index 0e124cd63d..3df31e3346 100644 --- a/src/file/drawing/inline/graphic/graphic.ts +++ b/src/file/drawing/inline/graphic/graphic.ts @@ -1,4 +1,4 @@ -import { IMediaData } from "file/media"; +import { IMediaData, IMediaDataTransformation } from "file/media"; import { XmlAttributeComponent, XmlComponent } from "file/xml-components"; import { GraphicData } from "./graphic-data"; @@ -14,7 +14,7 @@ class GraphicAttributes extends XmlAttributeComponent<{ export class Graphic extends XmlComponent { private readonly data: GraphicData; - constructor(mediaData: IMediaData, x: number, y: number) { + constructor(mediaData: IMediaData, transform: IMediaDataTransformation) { super("a:graphic"); this.root.push( new GraphicAttributes({ @@ -22,7 +22,7 @@ export class Graphic extends XmlComponent { }), ); - this.data = new GraphicData(mediaData, x, y); + this.data = new GraphicData(mediaData, transform); this.root.push(this.data); } diff --git a/src/file/drawing/inline/inline.ts b/src/file/drawing/inline/inline.ts index bf83e36764..2b124fc524 100644 --- a/src/file/drawing/inline/inline.ts +++ b/src/file/drawing/inline/inline.ts @@ -1,5 +1,5 @@ // http://officeopenxml.com/drwPicInline.php -import { IMediaData, IMediaDataDimensions } from "file/media"; +import { IMediaData, IMediaDataTransformation } from "file/media"; import { XmlComponent } from "file/xml-components"; import { DocProperties } from "./../doc-properties/doc-properties"; import { EffectExtent } from "./../effect-extent/effect-extent"; @@ -12,7 +12,7 @@ export class Inline extends XmlComponent { private readonly extent: Extent; private readonly graphic: Graphic; - constructor(mediaData: IMediaData, private readonly dimensions: IMediaDataDimensions) { + constructor(mediaData: IMediaData, private readonly transform: IMediaDataTransformation) { super("wp:inline"); this.root.push( @@ -24,8 +24,8 @@ export class Inline extends XmlComponent { }), ); - this.extent = new Extent(dimensions.emus.x, dimensions.emus.y); - this.graphic = new Graphic(mediaData, dimensions.emus.x, dimensions.emus.y); + this.extent = new Extent(transform.emus.x, transform.emus.y); + this.graphic = new Graphic(mediaData, transform); this.root.push(this.extent); this.root.push(new EffectExtent()); @@ -35,8 +35,8 @@ export class Inline extends XmlComponent { } public scale(factorX: number, factorY: number): void { - const newX = Math.round(this.dimensions.emus.x * factorX); - const newY = Math.round(this.dimensions.emus.y * factorY); + const newX = Math.round(this.transform.emus.x * factorX); + const newY = Math.round(this.transform.emus.y * factorY); this.extent.setXY(newX, newY); this.graphic.setXY(newX, newY); diff --git a/src/file/media/data.ts b/src/file/media/data.ts index c49457b803..020317980d 100644 --- a/src/file/media/data.ts +++ b/src/file/media/data.ts @@ -1,4 +1,4 @@ -export interface IMediaDataDimensions { +export interface IMediaDataTransformation { readonly pixels: { readonly x: number; readonly y: number; @@ -7,13 +7,18 @@ export interface IMediaDataDimensions { readonly x: number; readonly y: number; }; + readonly flip?: { + readonly vertical?: boolean; + readonly horizontal?: boolean; + }; + readonly rotation?: number; } export interface IMediaData { readonly stream: Buffer | Uint8Array | ArrayBuffer; readonly path?: string; readonly fileName: string; - readonly dimensions: IMediaDataDimensions; + readonly transformation: IMediaDataTransformation; } // Needed because of: https://github.com/s-panferov/awesome-typescript-loader/issues/432 diff --git a/src/file/media/media.spec.ts b/src/file/media/media.spec.ts index d3446ea0c1..3342bca29d 100644 --- a/src/file/media/media.spec.ts +++ b/src/file/media/media.spec.ts @@ -21,7 +21,14 @@ describe("Media", () => { describe("#addImage", () => { it("should add image", () => { const file = new File(); - const image = Media.addImage(file, ""); + const image = Media.addImage({ + document: file, + data: "", + transformation: { + width: 100, + height: 100, + }, + }); let tree = new Formatter().format(new Paragraph(image)); expect(tree["w:p"]).to.be.an.instanceof(Array); @@ -34,7 +41,14 @@ describe("Media", () => { // tslint:disable-next-line:no-any const file = new File(); - const image1 = Media.addImage(file, "test"); + const image1 = Media.addImage({ + document: file, + data: "test", + transformation: { + width: 100, + height: 100, + }, + }); const tree = new Formatter().format(new Paragraph(image1)); const inlineElements = tree["w:p"][0]["w:r"][0]["w:drawing"][0]["wp:inline"]; const graphicData = inlineElements.find((x) => x["a:graphic"]); @@ -46,7 +60,14 @@ describe("Media", () => { }, }); - const image2 = Media.addImage(file, "test"); + const image2 = Media.addImage({ + document: file, + data: "test", + transformation: { + width: 100, + height: 100, + }, + }); const tree2 = new Formatter().format(new Paragraph(image2)); const inlineElements2 = tree2["w:p"][0]["w:r"][0]["w:drawing"][0]["wp:inline"]; const graphicData2 = inlineElements2.find((x) => x["a:graphic"]); @@ -62,24 +83,32 @@ describe("Media", () => { describe("#addMedia", () => { it("should add media", () => { - const image = new Media().addMedia(""); + const image = new Media().addMedia("", { + width: 100, + height: 100, + }); expect(image.fileName).to.equal("test.png"); - expect(image.dimensions).to.deep.equal({ + expect(image.transformation).to.deep.equal({ pixels: { x: 100, y: 100, }, + flip: undefined, emus: { x: 952500, y: 952500, }, + rotation: undefined, }); }); it("should return UInt8Array if atob is present", () => { global.atob = () => "atob result"; - const image = new Media().addMedia(""); + const image = new Media().addMedia("", { + width: 100, + height: 100, + }); expect(image.stream).to.be.an.instanceof(Uint8Array); // tslint:disable-next-line: no-any @@ -89,7 +118,10 @@ describe("Media", () => { it("should use data as is if its not a string", () => { global.atob = () => "atob result"; - const image = new Media().addMedia(Buffer.from("")); + const image = new Media().addMedia(Buffer.from(""), { + width: 100, + height: 100, + }); expect(image.stream).to.be.an.instanceof(Uint8Array); // tslint:disable-next-line: no-any @@ -100,20 +132,25 @@ describe("Media", () => { describe("#getMedia", () => { it("should get media", () => { const media = new Media(); - media.addMedia(""); + media.addMedia("", { + width: 100, + height: 100, + }); const image = media.getMedia("test.png"); expect(image.fileName).to.equal("test.png"); - expect(image.dimensions).to.deep.equal({ + expect(image.transformation).to.deep.equal({ pixels: { x: 100, y: 100, }, + flip: undefined, emus: { x: 952500, y: 952500, }, + rotation: undefined, }); }); @@ -127,7 +164,15 @@ describe("Media", () => { describe("#Array", () => { it("Get images as array", () => { const media = new Media(); - media.addMedia(""); + media.addMedia("", { + width: 100, + height: 100, + flip: { + vertical: true, + horizontal: true, + }, + rotation: 90, + }); const array = media.Array; expect(array).to.be.an.instanceof(Array); @@ -135,15 +180,20 @@ describe("Media", () => { const image = array[0]; expect(image.fileName).to.equal("test.png"); - expect(image.dimensions).to.deep.equal({ + expect(image.transformation).to.deep.equal({ pixels: { x: 100, y: 100, }, + flip: { + vertical: true, + horizontal: true, + }, emus: { x: 952500, y: 952500, }, + rotation: 5400000, }); }); }); diff --git a/src/file/media/media.ts b/src/file/media/media.ts index 857128d254..a73111849d 100644 --- a/src/file/media/media.ts +++ b/src/file/media/media.ts @@ -1,22 +1,31 @@ import { uniqueId } from "convenience-functions"; -import { IDrawingOptions } from "../drawing"; +import { IFloating } from "../drawing"; import { File } from "../file"; import { PictureRun } from "../paragraph"; import { IMediaData } from "./data"; // import { Image } from "./image"; +interface IMediaTransformation { + readonly width: number; + readonly height: number; + readonly flip?: { + readonly vertical?: boolean; + readonly horizontal?: boolean; + }; + readonly rotation?: number; +} + export class Media { - public static addImage( - file: File, - buffer: Buffer | string | Uint8Array | ArrayBuffer, - width?: number, - height?: number, - drawingOptions?: IDrawingOptions, - ): PictureRun { + public static addImage(options: { + readonly document: File; + readonly data: Buffer | string | Uint8Array | ArrayBuffer; + readonly transformation: IMediaTransformation; + readonly floating?: IFloating; + }): PictureRun { // Workaround to expose id without exposing to API - const mediaData = file.Media.addMedia(buffer, width, height); - return new PictureRun(mediaData, drawingOptions); + const mediaData = options.document.Media.addMedia(options.data, options.transformation); + return new PictureRun(mediaData, { floating: options.floating }); } private readonly map: Map; @@ -35,22 +44,13 @@ export class Media { return data; } - public addMedia(buffer: Buffer | string | Uint8Array | ArrayBuffer, width: number = 100, height: number = 100): IMediaData { - const key = `${uniqueId()}.png`; - - return this.createMedia( - key, - { - width: width, - height: height, - }, - buffer, - ); + public addMedia(buffer: Buffer | string | Uint8Array | ArrayBuffer, transformation: IMediaTransformation): IMediaData { + return this.createMedia(`${uniqueId()}.png`, transformation, buffer); } private createMedia( key: string, - dimensions: { readonly width: number; readonly height: number }, + transformation: IMediaTransformation, data: Buffer | string | Uint8Array | ArrayBuffer, filePath?: string, ): IMediaData { @@ -60,15 +60,17 @@ export class Media { stream: newData, path: filePath, fileName: key, - dimensions: { + transformation: { pixels: { - x: Math.round(dimensions.width), - y: Math.round(dimensions.height), + x: Math.round(transformation.width), + y: Math.round(transformation.height), }, emus: { - x: Math.round(dimensions.width * 9525), - y: Math.round(dimensions.height * 9525), + x: Math.round(transformation.width * 9525), + y: Math.round(transformation.height * 9525), }, + flip: transformation.flip, + rotation: transformation.rotation ? transformation.rotation * 60000 : undefined, }, }; diff --git a/src/import-dotx/import-dotx.ts b/src/import-dotx/import-dotx.ts index 4c77ea75be..69a1ff0bcc 100644 --- a/src/import-dotx/import-dotx.ts +++ b/src/import-dotx/import-dotx.ts @@ -159,7 +159,10 @@ export class ImportDotx { for (const r of wrapperImagesReferences) { const buffer = await zipContent.files[`word/${r.target}`].async("nodebuffer"); - const mediaData = media.addMedia(buffer); + const mediaData = media.addMedia(buffer, { + width: 100, + height: 100, + }); wrapper.Relationships.createRelationship( r.id,