Make adding images declarative and simple

This commit is contained in:
Dolan
2021-03-18 02:48:37 +00:00
parent c8db70b3b7
commit caf188caae
25 changed files with 1585 additions and 550 deletions

View File

@ -16,7 +16,6 @@ export interface IMediaDataTransformation {
export interface IMediaData {
readonly stream: Buffer | Uint8Array | ArrayBuffer;
readonly path?: string;
readonly fileName: string;
readonly transformation: IMediaDataTransformation;
}

View File

@ -3,10 +3,7 @@ import { expect } from "chai";
import { SinonStub, stub } from "sinon";
import * as convenienceFunctions from "convenience-functions";
import { Formatter } from "export/formatter";
import { File } from "../file";
import { Paragraph } from "../paragraph";
import { Media } from "./media";
describe("Media", () => {
@ -18,69 +15,6 @@ describe("Media", () => {
(convenienceFunctions.uniqueId as SinonStub).restore();
});
describe("#addImage", () => {
it("should add image", () => {
const file = new 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);
tree = new Formatter().format(image);
expect(tree["w:r"]).to.be.an.instanceof(Array);
});
it("should ensure the correct relationship id is used when adding image", () => {
// tslint:disable-next-line:no-any
const file = new File();
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"]);
expect(graphicData["a:graphic"][1]["a:graphicData"][1]["pic:pic"][2]["pic:blipFill"][0]["a:blip"]).to.deep.equal({
_attr: {
"r:embed": `rId{test.png}`,
cstate: "none",
},
});
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"]);
expect(graphicData2["a:graphic"][1]["a:graphicData"][1]["pic:pic"][2]["pic:blipFill"][0]["a:blip"]).to.deep.equal({
_attr: {
"r:embed": `rId{test.png}`,
cstate: "none",
},
});
});
});
describe("#addMedia", () => {
it("should add media", () => {
const image = new Media().addMedia("", {
@ -129,35 +63,30 @@ describe("Media", () => {
});
});
describe("#getMedia", () => {
it("should get media", () => {
describe("#addImage", () => {
it("should add media", () => {
const media = new Media();
media.addMedia("", {
width: 100,
height: 100,
});
const image = media.getMedia("test.png");
expect(image.fileName).to.equal("test.png");
expect(image.transformation).to.deep.equal({
pixels: {
x: 100,
y: 100,
media.addImage("test2.png", {
stream: Buffer.from(""),
fileName: "",
transformation: {
pixels: {
x: Math.round(1),
y: Math.round(1),
},
emus: {
x: Math.round(1 * 9525),
y: Math.round(1 * 9525),
},
},
flip: undefined,
emus: {
x: 952500,
y: 952500,
},
rotation: undefined,
});
});
it("Get media", () => {
const media = new Media();
expect(() => media.getMedia("test.png")).to.throw();
expect(media.Array).to.be.lengthOf(2);
});
});

View File

@ -1,12 +1,9 @@
import { uniqueId } from "convenience-functions";
import { IFloating } from "../drawing";
import { File } from "../file";
import { PictureRun } from "../paragraph";
import { IMediaData } from "./data";
// import { Image } from "./image";
interface IMediaTransformation {
export interface IMediaTransformation {
readonly width: number;
readonly height: number;
readonly flip?: {
@ -17,48 +14,19 @@ interface IMediaTransformation {
}
export class Media {
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 = options.document.Media.addMedia(options.data, options.transformation);
return new PictureRun(mediaData, { floating: options.floating });
}
private readonly map: Map<string, IMediaData>;
constructor() {
this.map = new Map<string, IMediaData>();
}
public getMedia(key: string): IMediaData {
const data = this.map.get(key);
public addMedia(data: Buffer | string | Uint8Array | ArrayBuffer, transformation: IMediaTransformation): IMediaData {
const key = `${uniqueId()}.png`;
if (data === undefined) {
throw new Error(`Cannot find image with the key ${key}`);
}
return data;
}
public addMedia(buffer: Buffer | string | Uint8Array | ArrayBuffer, transformation: IMediaTransformation): IMediaData {
return this.createMedia(`${uniqueId()}.png`, transformation, buffer);
}
private createMedia(
key: string,
transformation: IMediaTransformation,
data: Buffer | string | Uint8Array | ArrayBuffer,
filePath?: string,
): IMediaData {
const newData = typeof data === "string" ? this.convertDataURIToBinary(data) : data;
const imageData: IMediaData = {
stream: newData,
path: filePath,
fileName: key,
transformation: {
pixels: {
@ -79,14 +47,12 @@ export class Media {
return imageData;
}
public addImage(key: string, mediaData: IMediaData): void {
this.map.set(key, mediaData);
}
public get Array(): readonly IMediaData[] {
const array = new Array<IMediaData>();
this.map.forEach((data) => {
array.push(data);
});
return array;
return Array.from(this.map.values());
}
private convertDataURIToBinary(dataURI: string): Uint8Array {