Change ImageRun keys to be based on image data content (#2681)

Co-authored-by: Dolan <dolan_miu@hotmail.com>
This commit is contained in:
mustache1up
2024-10-10 21:13:51 -03:00
committed by GitHub
parent 021f1b0c4d
commit e86dbd3398
6 changed files with 102 additions and 31 deletions

View File

@ -1,21 +1,12 @@
import { afterAll, beforeAll, describe, expect, it, vi } from "vitest";
import { describe, expect, it, vi } from "vitest";
import { Formatter } from "@export/formatter";
import { IViewWrapper } from "@file/document-wrapper";
import { File } from "@file/file";
import * as convenienceFunctions from "@util/convenience-functions";
import { ImageRun } from "./image-run";
describe("ImageRun", () => {
beforeAll(() => {
vi.spyOn(convenienceFunctions, "uniqueId").mockReturnValue("test-unique-id");
});
afterAll(() => {
vi.resetAllMocks();
});
describe("#constructor()", () => {
it("should create with Buffer", () => {
const currentImageRun = new ImageRun({
@ -193,7 +184,8 @@ describe("ImageRun", () => {
"a:blip": {
_attr: {
cstate: "none",
"r:embed": "rId{test-unique-id.png}",
"r:embed":
"rId{da39a3ee5e6b4b0d3255bfef95601890afd80709.png}",
},
},
},
@ -445,7 +437,8 @@ describe("ImageRun", () => {
"a:blip": {
_attr: {
cstate: "none",
"r:embed": "rId{test-unique-id.png}",
"r:embed":
"rId{da39a3ee5e6b4b0d3255bfef95601890afd80709.png}",
},
},
},
@ -700,7 +693,8 @@ describe("ImageRun", () => {
"a:blip": {
_attr: {
cstate: "none",
"r:embed": "rId{test-unique-id.png}",
"r:embed":
"rId{da39a3ee5e6b4b0d3255bfef95601890afd80709.png}",
},
},
},
@ -955,7 +949,8 @@ describe("ImageRun", () => {
"a:blip": {
_attr: {
cstate: "none",
"r:embed": "rId{test-unique-id.png}",
"r:embed":
"rId{da39a3ee5e6b4b0d3255bfef95601890afd80709.png}",
},
},
},
@ -1090,7 +1085,8 @@ describe("ImageRun", () => {
{
_attr: {
cstate: "none",
"r:embed": "rId{test-unique-id.png}",
"r:embed":
"rId{da39a3ee5e6b4b0d3255bfef95601890afd80709.png}",
},
},
{
@ -1106,7 +1102,7 @@ describe("ImageRun", () => {
"asvg:svgBlip": {
_attr: expect.objectContaining({
"r:embed":
"rId{test-unique-id.svg}",
"rId{da39a3ee5e6b4b0d3255bfef95601890afd80709.svg}",
}),
},
},
@ -1131,5 +1127,55 @@ describe("ImageRun", () => {
],
});
});
it("using same data twice should use same media key", () => {
const imageRunStringData = new ImageRun({
type: "png",
data: "DATA",
transformation: {
width: 100,
height: 100,
rotation: 42,
},
});
const imageRunBufferData = new ImageRun({
type: "png",
data: Buffer.from("DATA"),
transformation: {
width: 200,
height: 200,
rotation: 45,
},
});
const addImageSpy = vi.fn();
const context = {
file: {
Media: {
addImage: addImageSpy,
},
} as unknown as File,
viewWrapper: {} as unknown as IViewWrapper,
stack: [],
};
new Formatter().format(imageRunStringData, context);
new Formatter().format(imageRunBufferData, context);
const expectedHash = "580393f5a94fb469585f5dd2a6859a4aab899f37";
expect(addImageSpy).toHaveBeenCalledTimes(2);
expect(addImageSpy).toHaveBeenNthCalledWith(
1,
`${expectedHash}.png`,
expect.objectContaining({ fileName: `${expectedHash}.png` }),
);
expect(addImageSpy).toHaveBeenNthCalledWith(
2,
`${expectedHash}.png`,
expect.objectContaining({ fileName: `${expectedHash}.png` }),
);
});
});
});

View File

@ -1,4 +1,4 @@
import { uniqueId } from "@util/convenience-functions";
import { hashedId } from "@util/convenience-functions";
import { IContext, IXmlableObject } from "@file/xml-components";
import { DocPropertiesOptions } from "@file/drawing/doc-properties/doc-properties";
@ -76,20 +76,19 @@ const createImageData = (options: IImageOptions, key: string): Pick<IMediaData,
});
export class ImageRun extends Run {
private readonly key: string;
private readonly fallbackKey = `${uniqueId()}.png`;
private readonly imageData: IMediaData;
public constructor(options: IImageOptions) {
super({});
this.key = `${uniqueId()}.${options.type}`;
const hash = hashedId(options.data);
const key = `${hash}.${options.type}`;
this.imageData =
options.type === "svg"
? {
type: options.type,
...createImageData(options, this.key),
...createImageData(options, key),
fallback: {
type: options.fallback.type,
...createImageData(
@ -97,13 +96,13 @@ export class ImageRun extends Run {
...options.fallback,
transformation: options.transformation,
},
this.fallbackKey,
`${hashedId(options.fallback.data)}.${options.fallback.type}`,
),
},
}
: {
type: options.type,
...createImageData(options, this.key),
...createImageData(options, key),
};
const drawing = new Drawing(this.imageData, {
floating: options.floating,
@ -115,10 +114,10 @@ export class ImageRun extends Run {
}
public prepForXml(context: IContext): IXmlableObject | undefined {
context.file.Media.addImage(this.key, this.imageData);
context.file.Media.addImage(this.imageData.fileName, this.imageData);
if (this.imageData.type === "svg") {
context.file.Media.addImage(this.fallbackKey, this.imageData.fallback);
context.file.Media.addImage(this.imageData.fallback.fileName, this.imageData.fallback);
}
return super.prepForXml(context);