Remove id from media

This commit is contained in:
Dolan
2018-12-24 16:50:53 +00:00
parent d021a3995e
commit 8db52212ab
16 changed files with 181 additions and 120 deletions

17
demo/demo35.ts Normal file
View File

@ -0,0 +1,17 @@
// Simple example to add text to a document
// Import from 'docx' rather than '../build' if you install from npm
import * as fs from "fs";
import { Document, Packer, Paragraph, TextRun } from "../build";
var doc = new Document();
var paragraph = new Paragraph();
var link = doc.createHyperlink('http://www.example.com', 'Hyperlink');
link.bold();
paragraph.addHyperLink(link);
doc.addParagraph(paragraph);
const packer = new Packer();
packer.toBuffer(doc).then((buffer) => {
fs.writeFileSync("My Document.docx", buffer);
});

23
demo/demo36.ts Normal file
View File

@ -0,0 +1,23 @@
// Add images to header and footer
// Import from 'docx' rather than '../build' if you install from npm
import * as fs from "fs";
import { Document, Media, Packer, Table } from "../build";
const doc = new Document();
const image = Media.addImage(doc, fs.readFileSync("./demo/images/image1.jpeg"));
const table = new Table(2, 2);
table.getCell(1, 1).addContent(image.Paragraph);
// doc.createParagraph("Hello World");
doc.addTable(table);
// doc.Header.createImage(fs.readFileSync("./demo/images/pizza.gif"));
doc.Header.addTable(table);
// doc.Footer.createImage(fs.readFileSync("./demo/images/pizza.gif"));
const packer = new Packer();
packer.toBuffer(doc).then((buffer) => {
fs.writeFileSync("My Document.docx", buffer);
});

18
demo/demo37.ts Normal file
View File

@ -0,0 +1,18 @@
// Add images to header and footer
// Import from 'docx' rather than '../build' if you install from npm
import * as fs from "fs";
import { Document, Media, Packer } from "../build";
const doc = new Document();
const image = Media.addImage(doc, fs.readFileSync("./demo/images/image1.jpeg"));
doc.createParagraph("Hello World");
doc.Header.addImage(image);
doc.Header.createImage(fs.readFileSync("./demo/images/pizza.gif"));
doc.Header.createImage(fs.readFileSync("./demo/images/image1.jpeg"));
const packer = new Packer();
packer.toBuffer(doc).then((buffer) => {
fs.writeFileSync("My Document.docx", buffer);
});

View File

@ -0,0 +1,17 @@
import { IMediaData, Media } from "file/media";
export class ImageReplacer {
public replace(xmlData: string, mediaData: IMediaData[], offset: number): string {
let currentXmlData = xmlData;
mediaData.forEach((image, i) => {
currentXmlData = currentXmlData.replace(`{${image.fileName}}`, (offset + i).toString());
});
return currentXmlData;
}
public getMediaData(xmlData: string, media: Media): IMediaData[] {
return media.Array.filter((image) => xmlData.search(`{${image.fileName}}`) > 0);
}
}

View File

@ -3,6 +3,7 @@ import * as xml from "xml";
import { File } from "file"; import { File } from "file";
import { Formatter } from "../formatter"; import { Formatter } from "../formatter";
import { ImageReplacer } from "./image-replacer";
interface IXmlifyedFile { interface IXmlifyedFile {
readonly data: string; readonly data: string;
@ -28,18 +29,15 @@ interface IXmlifyedFileMapping {
export class Compiler { export class Compiler {
private readonly formatter: Formatter; private readonly formatter: Formatter;
private readonly imageReplacer: ImageReplacer;
constructor() { constructor() {
this.formatter = new Formatter(); this.formatter = new Formatter();
this.imageReplacer = new ImageReplacer();
} }
public async compile(file: File): Promise<JSZip> { public async compile(file: File): Promise<JSZip> {
const zip = new JSZip(); const zip = new JSZip();
// Run precompile steps
file.onCompile();
file.Headers.forEach((header) => header.onCompile());
const xmlifiedFileMapping = this.xmlifyFile(file); const xmlifiedFileMapping = this.xmlifyFile(file);
for (const key in xmlifiedFileMapping) { for (const key in xmlifiedFileMapping) {
@ -63,26 +61,39 @@ export class Compiler {
zip.file(`word/media/${data.fileName}`, mediaData); zip.file(`word/media/${data.fileName}`, mediaData);
} }
for (const header of file.Headers) {
for (const data of header.Media.Array) {
zip.file(`word/media/${data.fileName}`, data.stream);
}
}
for (const footer of file.Footers) {
for (const data of footer.Media.Array) {
zip.file(`word/media/${data.fileName}`, data.stream);
}
}
return zip; return zip;
} }
private xmlifyFile(file: File): IXmlifyedFileMapping { private xmlifyFile(file: File): IXmlifyedFileMapping {
file.verifyUpdateFields(); file.verifyUpdateFields();
const documentRelationshipCount = file.DocumentRelationships.RelationshipCount + 1;
return { return {
Relationships: {
data: (() => {
const xmlData = xml(this.formatter.format(file.Document));
const mediaDatas = this.imageReplacer.getMediaData(xmlData, file.Media);
mediaDatas.forEach((mediaData, i) => {
file.DocumentRelationships.createRelationship(
documentRelationshipCount + i,
"http://schemas.openxmlformats.org/officeDocument/2006/relationships/image",
`media/${mediaData.fileName}`,
);
});
return xml(this.formatter.format(file.DocumentRelationships));
})(),
path: "word/_rels/document.xml.rels",
},
Document: { Document: {
data: xml(this.formatter.format(file.Document), true), data: (() => {
const tempXmlData = xml(this.formatter.format(file.Document), true);
const mediaDatas = this.imageReplacer.getMediaData(tempXmlData, file.Media);
const xmlData = this.imageReplacer.replace(tempXmlData, mediaDatas, documentRelationshipCount);
return xmlData;
})(),
path: "word/document.xml", path: "word/document.xml",
}, },
Styles: { Styles: {
@ -102,30 +113,66 @@ export class Compiler {
data: xml(this.formatter.format(file.Numbering)), data: xml(this.formatter.format(file.Numbering)),
path: "word/numbering.xml", path: "word/numbering.xml",
}, },
Relationships: {
data: xml(this.formatter.format(file.DocumentRelationships)),
path: "word/_rels/document.xml.rels",
},
FileRelationships: { FileRelationships: {
data: xml(this.formatter.format(file.FileRelationships)), data: xml(this.formatter.format(file.FileRelationships)),
path: "_rels/.rels", path: "_rels/.rels",
}, },
Headers: file.Headers.map((headerWrapper, index) => ({ HeaderRelationships: file.Headers.map((headerWrapper, index) => {
data: xml(this.formatter.format(headerWrapper.Header)), const xmlData = xml(this.formatter.format(headerWrapper.Header));
path: `word/header${index + 1}.xml`, const mediaDatas = this.imageReplacer.getMediaData(xmlData, file.Media);
})),
Footers: file.Footers.map((footerWrapper, index) => ({ mediaDatas.forEach((mediaData, i) => {
data: xml(this.formatter.format(footerWrapper.Footer)), headerWrapper.Relationships.createRelationship(
path: `word/footer${index + 1}.xml`, i,
})), "http://schemas.openxmlformats.org/officeDocument/2006/relationships/image",
HeaderRelationships: file.Headers.map((headerWrapper, index) => ({ `media/${mediaData.fileName}`,
data: xml(this.formatter.format(headerWrapper.Relationships)), );
path: `word/_rels/header${index + 1}.xml.rels`, });
})),
FooterRelationships: file.Footers.map((footerWrapper, index) => ({ return {
data: xml(this.formatter.format(footerWrapper.Relationships)), data: xml(this.formatter.format(headerWrapper.Relationships)),
path: `word/_rels/footer${index + 1}.xml.rels`, path: `word/_rels/header${index + 1}.xml.rels`,
})), };
}),
FooterRelationships: file.Footers.map((footerWrapper, index) => {
const xmlData = xml(this.formatter.format(footerWrapper.Footer));
const mediaDatas = this.imageReplacer.getMediaData(xmlData, file.Media);
mediaDatas.forEach((mediaData, i) => {
footerWrapper.Relationships.createRelationship(
i,
"http://schemas.openxmlformats.org/officeDocument/2006/relationships/image",
`media/${mediaData.fileName}`,
);
});
return {
data: xml(this.formatter.format(footerWrapper.Relationships)),
path: `word/_rels/footer${index + 1}.xml.rels`,
};
}),
Headers: file.Headers.map((headerWrapper, index) => {
const tempXmlData = xml(this.formatter.format(headerWrapper.Header));
const mediaDatas = this.imageReplacer.getMediaData(tempXmlData, file.Media);
// TODO: 0 needs to be changed when headers get relationships of their own
const xmlData = this.imageReplacer.replace(tempXmlData, mediaDatas, 0);
return {
data: xmlData,
path: `word/header${index + 1}.xml`,
};
}),
Footers: file.Footers.map((footerWrapper, index) => {
const tempXmlData = xml(this.formatter.format(footerWrapper.Footer));
const mediaDatas = this.imageReplacer.getMediaData(tempXmlData, file.Media);
// TODO: 0 needs to be changed when headers get relationships of their own
const xmlData = this.imageReplacer.replace(tempXmlData, mediaDatas, 0);
return {
data: xmlData,
path: `word/footer${index + 1}.xml`,
};
}),
ContentTypes: { ContentTypes: {
data: xml(this.formatter.format(file.ContentTypes)), data: xml(this.formatter.format(file.ContentTypes)),
path: "[Content_Types].xml", path: "[Content_Types].xml",

View File

@ -9,7 +9,6 @@ import { Anchor } from "./anchor";
function createDrawing(drawingOptions: IDrawingOptions): Anchor { function createDrawing(drawingOptions: IDrawingOptions): Anchor {
return new Anchor( return new Anchor(
{ {
referenceId: 1,
fileName: "test.png", fileName: "test.png",
stream: new Buffer(""), stream: new Buffer(""),
dimensions: { dimensions: {

View File

@ -11,7 +11,6 @@ function createDrawing(drawingOptions?: IDrawingOptions): Drawing {
return new Drawing( return new Drawing(
{ {
fileName: "test.jpg", fileName: "test.jpg",
referenceId: 1,
stream: Buffer.from(imageBase64Data, "base64"), stream: Buffer.from(imageBase64Data, "base64"),
path: path, path: path,
dimensions: { dimensions: {

View File

@ -13,7 +13,6 @@ import { IFileProperties } from "./file-properties";
import { FooterWrapper, IDocumentFooter } from "./footer-wrapper"; import { FooterWrapper, IDocumentFooter } from "./footer-wrapper";
import { FootNotes } from "./footnotes"; import { FootNotes } from "./footnotes";
import { HeaderWrapper, IDocumentHeader } from "./header-wrapper"; import { HeaderWrapper, IDocumentHeader } from "./header-wrapper";
import { IOnCompile } from "./life-cycles";
import { Image, Media } from "./media"; import { Image, Media } from "./media";
import { Numbering } from "./numbering"; import { Numbering } from "./numbering";
import { Bookmark, Hyperlink, Paragraph } from "./paragraph"; import { Bookmark, Hyperlink, Paragraph } from "./paragraph";
@ -26,7 +25,7 @@ import { DefaultStylesFactory } from "./styles/factory";
import { Table } from "./table"; import { Table } from "./table";
import { TableOfContents } from "./table-of-contents"; import { TableOfContents } from "./table-of-contents";
export class File implements IOnCompile { export class File {
// tslint:disable-next-line:readonly-keyword // tslint:disable-next-line:readonly-keyword
private currentRelationshipId: number = 1; private currentRelationshipId: number = 1;
@ -223,11 +222,6 @@ export class File implements IOnCompile {
} }
} }
public onCompile(): void {
// this.media.Array.forEach((media) => {
// });
}
private addHeaderToDocument(header: HeaderWrapper, type: HeaderReferenceType = HeaderReferenceType.DEFAULT): void { private addHeaderToDocument(header: HeaderWrapper, type: HeaderReferenceType = HeaderReferenceType.DEFAULT): void {
this.headers.push({ header, type }); this.headers.push({ header, type });
this.docRelationships.createRelationship( this.docRelationships.createRelationship(

View File

@ -2,7 +2,6 @@ import { XmlComponent } from "file/xml-components";
import { FooterReferenceType } from "./document"; import { FooterReferenceType } from "./document";
import { Footer } from "./footer/footer"; import { Footer } from "./footer/footer";
import { IOnCompile } from "./life-cycles";
import { Image, Media } from "./media"; import { Image, Media } from "./media";
import { ImageParagraph, Paragraph } from "./paragraph"; import { ImageParagraph, Paragraph } from "./paragraph";
import { Relationships } from "./relationships"; import { Relationships } from "./relationships";
@ -13,7 +12,7 @@ export interface IDocumentFooter {
readonly type: FooterReferenceType; readonly type: FooterReferenceType;
} }
export class FooterWrapper implements IOnCompile { export class FooterWrapper {
private readonly footer: Footer; private readonly footer: Footer;
private readonly relationships: Relationships; private readonly relationships: Relationships;
@ -45,7 +44,7 @@ export class FooterWrapper implements IOnCompile {
} }
public createImage(image: Buffer | string | Uint8Array | ArrayBuffer, width?: number, height?: number): void { public createImage(image: Buffer | string | Uint8Array | ArrayBuffer, width?: number, height?: number): void {
const mediaData = this.media.addMedia(image, this.relationships.RelationshipCount, width, height); const mediaData = this.media.addMedia(image, width, height);
this.addImage(new Image(new ImageParagraph(mediaData))); this.addImage(new Image(new ImageParagraph(mediaData)));
} }
@ -54,16 +53,6 @@ export class FooterWrapper implements IOnCompile {
return this; return this;
} }
public onCompile(): void {
this.media.Array.forEach((mediaData) => {
this.relationships.createRelationship(
mediaData.referenceId,
"http://schemas.openxmlformats.org/officeDocument/2006/relationships/image",
`media/${mediaData.fileName}`,
);
});
}
public get Footer(): Footer { public get Footer(): Footer {
return this.footer; return this.footer;
} }

View File

@ -2,7 +2,6 @@ import { XmlComponent } from "file/xml-components";
import { HeaderReferenceType } from "./document"; import { HeaderReferenceType } from "./document";
import { Header } from "./header/header"; import { Header } from "./header/header";
import { IOnCompile } from "./life-cycles";
import { Image, Media } from "./media"; import { Image, Media } from "./media";
import { ImageParagraph, Paragraph } from "./paragraph"; import { ImageParagraph, Paragraph } from "./paragraph";
import { Relationships } from "./relationships"; import { Relationships } from "./relationships";
@ -13,7 +12,7 @@ export interface IDocumentHeader {
readonly type: HeaderReferenceType; readonly type: HeaderReferenceType;
} }
export class HeaderWrapper implements IOnCompile { export class HeaderWrapper {
private readonly header: Header; private readonly header: Header;
private readonly relationships: Relationships; private readonly relationships: Relationships;
@ -45,7 +44,7 @@ export class HeaderWrapper implements IOnCompile {
} }
public createImage(image: Buffer | string | Uint8Array | ArrayBuffer, width?: number, height?: number): void { public createImage(image: Buffer | string | Uint8Array | ArrayBuffer, width?: number, height?: number): void {
const mediaData = this.media.addMedia(image, this.relationships.RelationshipCount, width, height); const mediaData = this.media.addMedia(image, width, height);
this.addImage(new Image(new ImageParagraph(mediaData))); this.addImage(new Image(new ImageParagraph(mediaData)));
} }
@ -54,16 +53,6 @@ export class HeaderWrapper implements IOnCompile {
return this; return this;
} }
public onCompile(): void {
this.media.Array.forEach((mediaData) => {
this.relationships.createRelationship(
mediaData.referenceId,
"http://schemas.openxmlformats.org/officeDocument/2006/relationships/image",
`media/${mediaData.fileName}`,
);
});
}
public get Header(): Header { public get Header(): Header {
return this.header; return this.header;
} }

View File

@ -1,9 +0,0 @@
export interface IOnCompile {
readonly onCompile: () => void;
}
// Needed because of: https://github.com/s-panferov/awesome-typescript-loader/issues/432
/**
* @ignore
*/
export const WORKAROUND4 = "";

View File

@ -10,7 +10,6 @@ export interface IMediaDataDimensions {
} }
export interface IMediaData { export interface IMediaData {
readonly referenceId: number;
readonly stream: Buffer | Uint8Array | ArrayBuffer; readonly stream: Buffer | Uint8Array | ArrayBuffer;
readonly path?: string; readonly path?: string;
readonly fileName: string; readonly fileName: string;

View File

@ -1,5 +1,6 @@
// tslint:disable:object-literal-key-quotes // tslint:disable:object-literal-key-quotes
import { expect } from "chai"; import { expect } from "chai";
import { stub } from "sinon";
import { Formatter } from "export/formatter"; import { Formatter } from "export/formatter";
@ -20,16 +21,18 @@ describe("Media", () => {
}); });
it("should ensure the correct relationship id is used when adding image", () => { it("should ensure the correct relationship id is used when adding image", () => {
// tslint:disable-next-line:no-any
stub(Media as any, "generateId").callsFake(() => "testId");
const file = new File(); const file = new File();
const image1 = Media.addImage(file, "test"); const image1 = Media.addImage(file, "test");
const tree = new Formatter().format(image1.Paragraph); const tree = new Formatter().format(image1.Paragraph);
const inlineElements = tree["w:p"][1]["w:r"][1]["w:drawing"][0]["wp:inline"]; const inlineElements = tree["w:p"][1]["w:r"][1]["w:drawing"][0]["wp:inline"];
const graphicData = inlineElements.find((x) => x["a:graphic"]); const graphicData = inlineElements.find((x) => x["a:graphic"]);
expect(graphicData["a:graphic"][1]["a:graphicData"][1]["pic:pic"][2]["pic:blipFill"][0]["a:blip"][0]).to.deep.equal({ expect(graphicData["a:graphic"][1]["a:graphicData"][1]["pic:pic"][2]["pic:blipFill"][0]["a:blip"][0]).to.deep.equal({
_attr: { _attr: {
"r:embed": `rId${file.DocumentRelationships.RelationshipCount}`, "r:embed": `rId{testId.png}`,
cstate: "none", cstate: "none",
}, },
}); });
@ -41,7 +44,7 @@ describe("Media", () => {
expect(graphicData2["a:graphic"][1]["a:graphicData"][1]["pic:pic"][2]["pic:blipFill"][0]["a:blip"][0]).to.deep.equal({ expect(graphicData2["a:graphic"][1]["a:graphicData"][1]["pic:pic"][2]["pic:blipFill"][0]["a:blip"][0]).to.deep.equal({
_attr: { _attr: {
"r:embed": `rId${file.DocumentRelationships.RelationshipCount}`, "r:embed": `rId{testId.png}`,
cstate: "none", cstate: "none",
}, },
}); });
@ -53,9 +56,8 @@ describe("Media", () => {
// tslint:disable-next-line:no-any // tslint:disable-next-line:no-any
(Media as any).generateId = () => "test"; (Media as any).generateId = () => "test";
const image = new Media().addMedia("", 1); const image = new Media().addMedia("");
expect(image.fileName).to.equal("test.png"); expect(image.fileName).to.equal("test.png");
expect(image.referenceId).to.equal(1);
expect(image.dimensions).to.deep.equal({ expect(image.dimensions).to.deep.equal({
pixels: { pixels: {
x: 100, x: 100,
@ -74,7 +76,7 @@ describe("Media", () => {
// tslint:disable-next-line:no-any // tslint:disable-next-line:no-any
(Media as any).generateId = () => "test"; (Media as any).generateId = () => "test";
const image = new Media().addMedia("", 1); const image = new Media().addMedia("");
expect(image.stream).to.be.an.instanceof(Uint8Array); expect(image.stream).to.be.an.instanceof(Uint8Array);
}); });
}); });
@ -85,12 +87,11 @@ describe("Media", () => {
(Media as any).generateId = () => "test"; (Media as any).generateId = () => "test";
const media = new Media(); const media = new Media();
media.addMedia("", 1); media.addMedia("");
const image = media.getMedia("test.png"); const image = media.getMedia("test.png");
expect(image.fileName).to.equal("test.png"); expect(image.fileName).to.equal("test.png");
expect(image.referenceId).to.equal(1);
expect(image.dimensions).to.deep.equal({ expect(image.dimensions).to.deep.equal({
pixels: { pixels: {
x: 100, x: 100,
@ -116,7 +117,7 @@ describe("Media", () => {
(Media as any).generateId = () => "test"; (Media as any).generateId = () => "test";
const media = new Media(); const media = new Media();
media.addMedia("", 1); media.addMedia("");
const array = media.Array; const array = media.Array;
expect(array).to.be.an.instanceof(Array); expect(array).to.be.an.instanceof(Array);
@ -124,7 +125,6 @@ describe("Media", () => {
const image = array[0]; const image = array[0];
expect(image.fileName).to.equal("test.png"); expect(image.fileName).to.equal("test.png");
expect(image.referenceId).to.equal(1);
expect(image.dimensions).to.deep.equal({ expect(image.dimensions).to.deep.equal({
pixels: { pixels: {
x: 100, x: 100,

View File

@ -4,11 +4,6 @@ import { ImageParagraph } from "../paragraph";
import { IMediaData } from "./data"; import { IMediaData } from "./data";
import { Image } from "./image"; import { Image } from "./image";
interface IHackedFile {
// tslint:disable-next-line:readonly-keyword
currentRelationshipId: number;
}
export class Media { export class Media {
public static addImage( public static addImage(
file: File, file: File,
@ -18,14 +13,7 @@ export class Media {
drawingOptions?: IDrawingOptions, drawingOptions?: IDrawingOptions,
): Image { ): Image {
// Workaround to expose id without exposing to API // Workaround to expose id without exposing to API
const exposedFile = (file as {}) as IHackedFile; const mediaData = file.Media.addMedia(buffer, width, height);
const mediaData = file.Media.addMedia(buffer, exposedFile.currentRelationshipId++, width, height);
file.DocumentRelationships.createRelationship(
mediaData.referenceId,
"http://schemas.openxmlformats.org/officeDocument/2006/relationships/image",
`media/${mediaData.fileName}`,
);
return new Image(new ImageParagraph(mediaData, drawingOptions)); return new Image(new ImageParagraph(mediaData, drawingOptions));
} }
@ -57,17 +45,11 @@ export class Media {
return data; return data;
} }
public addMedia( public addMedia(buffer: Buffer | string | Uint8Array | ArrayBuffer, width: number = 100, height: number = 100): IMediaData {
buffer: Buffer | string | Uint8Array | ArrayBuffer,
referenceId: number,
width: number = 100,
height: number = 100,
): IMediaData {
const key = `${Media.generateId()}.png`; const key = `${Media.generateId()}.png`;
return this.createMedia( return this.createMedia(
key, key,
referenceId,
{ {
width: width, width: width,
height: height, height: height,
@ -78,7 +60,6 @@ export class Media {
private createMedia( private createMedia(
key: string, key: string,
relationshipsCount: number,
dimensions: { readonly width: number; readonly height: number }, dimensions: { readonly width: number; readonly height: number },
data: Buffer | string | Uint8Array | ArrayBuffer, data: Buffer | string | Uint8Array | ArrayBuffer,
filePath?: string, filePath?: string,
@ -86,7 +67,6 @@ export class Media {
const newData = typeof data === "string" ? this.convertDataURIToBinary(data) : data; const newData = typeof data === "string" ? this.convertDataURIToBinary(data) : data;
const imageData: IMediaData = { const imageData: IMediaData = {
referenceId: relationshipsCount,
stream: newData, stream: newData,
path: filePath, path: filePath,
fileName: key, fileName: key,

View File

@ -10,10 +10,9 @@ describe("Image", () => {
beforeEach(() => { beforeEach(() => {
image = new ImageParagraph({ image = new ImageParagraph({
referenceId: 0,
stream: new Buffer(""), stream: new Buffer(""),
path: "", path: "",
fileName: "", fileName: "test.png",
dimensions: { dimensions: {
pixels: { pixels: {
x: 10, x: 10,
@ -171,7 +170,7 @@ describe("Image", () => {
{ {
_attr: { _attr: {
cstate: "none", cstate: "none",
"r:embed": "rId0", "r:embed": "rId{test.png}",
}, },
}, },
], ],

View File

@ -166,10 +166,10 @@ export class ImportDotx {
for (const r of wrapperImagesReferences) { for (const r of wrapperImagesReferences) {
const buffer = await zipContent.files[`word/${r.target}`].async("nodebuffer"); const buffer = await zipContent.files[`word/${r.target}`].async("nodebuffer");
const mediaData = media.addMedia(buffer, r.id); const mediaData = media.addMedia(buffer);
wrapper.Relationships.createRelationship( wrapper.Relationships.createRelationship(
mediaData.referenceId, r.id,
"http://schemas.openxmlformats.org/officeDocument/2006/relationships/image", "http://schemas.openxmlformats.org/officeDocument/2006/relationships/image",
`media/${mediaData.fileName}`, `media/${mediaData.fileName}`,
); );