Skip to content

Commit 4bcbdf2

Browse files
committed
🐛 Fix #124
1 parent b456f34 commit 4bcbdf2

File tree

1 file changed

+104
-48
lines changed

1 file changed

+104
-48
lines changed

src/shapes/ole.ts

Lines changed: 104 additions & 48 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ import { FileHelper } from '../helper/file-helper';
22
import { XmlHelper } from '../helper/xml-helper';
33
import { Shape } from '../classes/shape';
44
import { ImportedElement, ShapeTargetType, Target } from '../types/types';
5-
import { XmlElement } from '../types/xml-types';
5+
import { XmlElement, RelationshipAttribute } from '../types/xml-types';
66
import IArchive from '../interfaces/iarchive';
77
import { RootPresTemplate } from '../interfaces/root-pres-template';
88
import { contentTracker } from '../helper/content-tracker';
@@ -55,6 +55,9 @@ export class OLEObject extends Shape {
5555
): Promise<OLEObject> {
5656
await this.prepare(targetTemplate, targetSlideNumber);
5757
await this.removeFromSlideTree();
58+
await this.removeOleObjectFile();
59+
await this.removeFromContentTypes();
60+
await this.removeFromSlideRels();
5861

5962
return this;
6063
}
@@ -66,8 +69,6 @@ export class OLEObject extends Shape {
6669
): Promise<void> {
6770
await this.setTarget(targetTemplate, targetSlideNumber);
6871

69-
this.targetNumber = this.targetTemplate.incrementCounter('oleObjects');
70-
7172
const allOleObjects = oleObjects || await OLEObject.getAllOnSlide(this.sourceArchive, this.targetSlideRelFile);
7273

7374
const oleObject = allOleObjects.find(obj => obj.rId === this.sourceRid);
@@ -77,17 +78,17 @@ export class OLEObject extends Shape {
7778

7879
const sourceFilePath = `ppt/embeddings/${oleObject.file.split('/').pop()}`;
7980

80-
await this.copyFiles(sourceFilePath);
81-
await this.appendTypes();
82-
}
81+
this.createdRid = await XmlHelper.getNextRelId(this.targetArchive, this.targetSlideRelFile);
8382

84-
private async copyFiles(sourceFilePath: string): Promise<void> {
85-
if (!this.createdRid) {
86-
this.createdRid = await XmlHelper.getNextRelId(this.targetArchive, this.targetSlideRelFile);
87-
}
83+
await this.copyOleObjectFile(sourceFilePath);
84+
await this.appendToContentTypes();
85+
await this.updateSlideRels();
86+
await this.updateSlideXml();
87+
}
8888

89+
private async copyOleObjectFile(sourceFilePath: string): Promise<void> {
8990
const fileExtension = this.getFileExtension(sourceFilePath);
90-
const targetFileName = `ppt/embeddings/${this.createdRid}${fileExtension}`;
91+
const targetFileName = `ppt/embeddings/oleObject${this.createdRid}${fileExtension}`;
9192

9293
try {
9394
await FileHelper.zipCopy(
@@ -102,46 +103,13 @@ export class OLEObject extends Shape {
102103
}
103104
}
104105

105-
private async appendTypes(): Promise<void> {
106-
await this.appendOleObjectToContentType();
107-
}
108-
109-
private async editTargetOleObjectRel(): Promise<void> {
110-
const targetRelFile = this.targetSlideRelFile;
111-
const relXml = await XmlHelper.getXmlFromArchive(this.targetArchive, targetRelFile);
112-
const relations = relXml.getElementsByTagName('Relationship');
113-
114-
Array.from(relations).forEach((element) => {
115-
const type = element.getAttribute('Type');
116-
if (type === 'http://schemas.openxmlformats.org/officeDocument/2006/relationships/oleObject') {
117-
const fileExtension = this.getFileExtension(element.getAttribute('Target'));
118-
this.updateTargetOleObjectRelation(
119-
element,
120-
'Target',
121-
`../embeddings/${this.createdRid}${fileExtension}`,
122-
);
123-
}
124-
});
125-
126-
XmlHelper.writeXmlToArchive(this.targetArchive, targetRelFile, relXml);
127-
}
128-
129-
private updateTargetOleObjectRelation(element: Element, attribute: string, value: string): void {
130-
element.setAttribute(attribute, value);
131-
contentTracker.trackRelation(this.targetSlideRelFile, {
132-
Id: element.getAttribute('Id') || '',
133-
Target: value,
134-
Type: element.getAttribute('Type') || '',
135-
});
136-
}
137-
138-
private async appendOleObjectToContentType(): Promise<void> {
106+
private async appendToContentTypes(): Promise<void> {
139107
const contentTypesPath = '[Content_Types].xml';
140108
const contentTypesXml = await XmlHelper.getXmlFromArchive(this.targetArchive, contentTypesPath);
141109

142110
const types = contentTypesXml.getElementsByTagName('Types')[0];
143111
const fileExtension = this.getFileExtension(this.oleObjectPath);
144-
const partName = `/ppt/embeddings/${this.createdRid}${fileExtension}`;
112+
const partName = `/ppt/embeddings/oleObject${this.createdRid}${fileExtension}`;
145113
const existingOverride = Array.from(types.getElementsByTagName('Override')).find(
146114
(override) => override.getAttribute('PartName') === partName
147115
);
@@ -152,10 +120,61 @@ export class OLEObject extends Shape {
152120
newOverride.setAttribute('ContentType', this.getContentType(fileExtension));
153121
types.appendChild(newOverride);
154122

155-
XmlHelper.writeXmlToArchive(this.targetArchive, contentTypesPath, contentTypesXml);
123+
await XmlHelper.writeXmlToArchive(this.targetArchive, contentTypesPath, contentTypesXml);
156124
}
157125
}
158126

127+
private async updateSlideRels(): Promise<void> {
128+
const targetRelFile = `ppt/${this.targetType}s/_rels/${this.targetType}${this.targetSlideNumber}.xml.rels`;
129+
const relXml = await XmlHelper.getXmlFromArchive(this.targetArchive, targetRelFile);
130+
const relationships = relXml.getElementsByTagName('Relationship');
131+
132+
const fileExtension = this.getFileExtension(this.oleObjectPath);
133+
const newTarget = `../embeddings/oleObject${this.createdRid}${fileExtension}`;
134+
135+
// Update or create the relationship
136+
let relationshipUpdated = false;
137+
for (let i = 0; i < relationships.length; i++) {
138+
if (relationships[i].getAttribute('Id') === this.sourceRid) {
139+
relationships[i].setAttribute('Id', this.createdRid);
140+
relationships[i].setAttribute('Target', newTarget);
141+
relationshipUpdated = true;
142+
break;
143+
}
144+
}
145+
146+
if (!relationshipUpdated) {
147+
const newRel = relXml.createElement('Relationship');
148+
newRel.setAttribute('Id', this.createdRid);
149+
newRel.setAttribute('Type', 'http://schemas.openxmlformats.org/officeDocument/2006/relationships/oleObject');
150+
newRel.setAttribute('Target', newTarget);
151+
relXml.documentElement.appendChild(newRel);
152+
}
153+
154+
await XmlHelper.writeXmlToArchive(this.targetArchive, targetRelFile, relXml);
155+
}
156+
157+
private async updateSlideXml(): Promise<void> {
158+
const slideXmlPath = `ppt/slides/slide${this.targetSlideNumber}.xml`;
159+
const slideXml = await XmlHelper.getXmlFromArchive(this.targetArchive, slideXmlPath);
160+
161+
const oleObjs = Array.from(slideXml.getElementsByTagName('p:oleObj'));
162+
oleObjs.forEach((oleObj) => {
163+
if (oleObj.getAttribute('r:id') === this.sourceRid) {
164+
oleObj.setAttribute('r:id', this.createdRid);
165+
const oleObjPr = oleObj.getElementsByTagName('p:oleObjPr')[0];
166+
if (oleObjPr) {
167+
const links = Array.from(oleObjPr.getElementsByTagName('a:link'));
168+
links.forEach(link => {
169+
link.setAttribute('r:id', this.createdRid);
170+
});
171+
}
172+
}
173+
});
174+
175+
await XmlHelper.writeXmlToArchive(this.targetArchive, slideXmlPath, slideXml);
176+
}
177+
159178
private getContentType(fileExtension: string): string {
160179
const contentTypes: { [key: string]: string } = {
161180
'.bin': 'application/vnd.openxmlformats-officedocument.oleObject',
@@ -169,6 +188,44 @@ export class OLEObject extends Shape {
169188
return contentTypes[fileExtension.toLowerCase()] || 'application/vnd.openxmlformats-officedocument.oleObject';
170189
}
171190

191+
private async removeOleObjectFile(): Promise<void> {
192+
const fileExtension = this.getFileExtension(this.oleObjectPath);
193+
const fileName = `ppt/embeddings/oleObject${this.createdRid}${fileExtension}`;
194+
await this.targetArchive.remove(fileName);
195+
}
196+
197+
private async removeFromContentTypes(): Promise<void> {
198+
const contentTypesPath = '[Content_Types].xml';
199+
const contentTypesXml = await XmlHelper.getXmlFromArchive(this.targetArchive, contentTypesPath);
200+
201+
const types = contentTypesXml.getElementsByTagName('Types')[0];
202+
const fileExtension = this.getFileExtension(this.oleObjectPath);
203+
const partName = `/ppt/embeddings/oleObject${this.createdRid}${fileExtension}`;
204+
const overrideToRemove = Array.from(types.getElementsByTagName('Override')).find(
205+
(override) => override.getAttribute('PartName') === partName
206+
);
207+
208+
if (overrideToRemove) {
209+
types.removeChild(overrideToRemove);
210+
await XmlHelper.writeXmlToArchive(this.targetArchive, contentTypesPath, contentTypesXml);
211+
}
212+
}
213+
214+
private async removeFromSlideRels(): Promise<void> {
215+
const targetRelFile = `ppt/${this.targetType}s/_rels/${this.targetType}${this.targetSlideNumber}.xml.rels`;
216+
const relXml = await XmlHelper.getXmlFromArchive(this.targetArchive, targetRelFile);
217+
const relationships = relXml.getElementsByTagName('Relationship');
218+
219+
for (let i = 0; i < relationships.length; i++) {
220+
if (relationships[i].getAttribute('Id') === this.createdRid) {
221+
relationships[i].parentNode.removeChild(relationships[i]);
222+
break;
223+
}
224+
}
225+
226+
await XmlHelper.writeXmlToArchive(this.targetArchive, targetRelFile, relXml);
227+
}
228+
172229
static async getAllOnSlide(
173230
archive: IArchive,
174231
relsPath: string,
@@ -199,6 +256,5 @@ export class OLEObject extends Shape {
199256
oleObjects: Target[]
200257
): Promise<void> {
201258
await this.prepare(targetTemplate, targetSlideNumber, oleObjects);
202-
await this.editTargetOleObjectRel();
203259
}
204260
}

0 commit comments

Comments
 (0)