Skip to content

Commit 89e10e1

Browse files
committed
fix(master): status; add comments / ToDos
1 parent a171f62 commit 89e10e1

File tree

7 files changed

+89
-30
lines changed

7 files changed

+89
-30
lines changed
-11 KB
Binary file not shown.

src/automizer.ts

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -385,8 +385,7 @@ export default class Automizer implements IPresentationProps {
385385
*/
386386
public async writeSlides(): Promise<void> {
387387
await this.rootTemplate.countExistingSlides();
388-
this.status.max =
389-
this.rootTemplate.slides.length + this.rootTemplate.masters.length;
388+
this.status.max = this.rootTemplate.slides.length;
390389

391390
for (const slide of this.rootTemplate.slides) {
392391
await this.rootTemplate.appendSlide(slide);

src/classes/master.ts

Lines changed: 37 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -112,7 +112,7 @@ export class Master implements IMaster {
112112
*/
113113
unsupportedTags = [
114114
'p:custDataLst',
115-
//'mc:AlternateContent',
115+
'mc:AlternateContent',
116116
//'a14:imgProps',
117117
];
118118

@@ -195,7 +195,7 @@ export class Master implements IMaster {
195195
this.targetRelsPath = `ppt/slideMasters/_rels/slideMaster${this.targetNumber}.xml.rels`;
196196
this.sourceArchive = await this.sourceTemplate.archive;
197197

198-
this.status.info = 'Appending slideMaster ' + this.targetNumber;
198+
console.log('Importing slideMaster ' + this.targetNumber);
199199

200200
await this.copySlideFiles();
201201
await this.copyRelatedLayouts();
@@ -208,18 +208,27 @@ export class Master implements IMaster {
208208
}
209209

210210
await this.applyModifications();
211-
await this.cleanSlide();
212-
213-
this.status.increment();
211+
await this.cleanSlide(this.targetPath);
212+
213+
/**
214+
* ToDo: Integrity checks could be used in many places
215+
* to log warnings in case we have skipped out related contents from copying
216+
* to the target archive.
217+
*
218+
* By now, this is disabled because appendToSlideRels() could leave some
219+
* artifacts from unused relations.
220+
*/
221+
// await this.checkIntegrity();
214222
}
215223

216224
async copyRelatedLayouts(): Promise<Target[]> {
217-
const targetHelper = await new XmlRelationshipHelper().initialize(
225+
const masterToLayout = await new XmlRelationshipHelper().initialize(
218226
this.targetArchive,
219-
`ppt/slideMasters/_rels/slideMaster${this.targetNumber}.xml.rels`,
227+
`slideMaster${this.targetNumber}.xml.rels`,
228+
`ppt/slideMasters/_rels`,
220229
);
221230

222-
const targets = targetHelper.getTargetsByPrefix(
231+
const targets = masterToLayout.getTargetsByPrefix(
223232
'../slideLayouts/slideLayout',
224233
);
225234

@@ -245,12 +254,18 @@ export class Master implements IMaster {
245254

246255
const layoutTargetHelper = await new XmlRelationshipHelper().initialize(
247256
this.targetArchive,
248-
`ppt/slideLayouts/_rels/slideLayout${nextSlideLayoutNumber}.xml.rels`,
257+
`slideLayout${nextSlideLayoutNumber}.xml.rels`,
258+
`ppt/slideLayouts/_rels`,
249259
);
250260
const layoutToMaster = layoutTargetHelper.getTargetsByPrefix(
251261
'../slideMasters/slideMaster',
252262
);
253263
layoutToMaster[0].updateTargetIndex(this.targetNumber);
264+
await layoutTargetHelper.checkTargets(this.sourceArchive);
265+
266+
await this.cleanSlide(
267+
`ppt/slideLayouts/slideLayout${nextSlideLayoutNumber}.xml`,
268+
);
254269

255270
await this.appendSlideLayoutToContentType(
256271
this.targetArchive,
@@ -261,6 +276,15 @@ export class Master implements IMaster {
261276
return targets;
262277
}
263278

279+
async checkIntegrity(): Promise<void> {
280+
const masterToLayout = await new XmlRelationshipHelper().initialize(
281+
this.targetArchive,
282+
`slideMaster${this.targetNumber}.xml.rels`,
283+
`ppt/slideMasters/_rels`,
284+
);
285+
await masterToLayout.checkTargets(this.sourceArchive);
286+
}
287+
264288
async copyThemeFiles() {
265289
const targets = await XmlHelper.getRelationshipTargetsByPrefix(
266290
this.targetArchive,
@@ -665,17 +689,17 @@ export class Master implements IMaster {
665689
}
666690

667691
/**
668-
* ToDo: This equals the corresponding method in slide.ts
692+
* ToDo: This *almost* equals the corresponding method in slide.ts
669693
*
670694
* Removes all unsupported tags from slide xml.
671695
* E.g. added relations & tags by Thinkcell cannot
672696
* be processed by pptx-automizer at the moment.
673697
* @internal
674698
*/
675-
async cleanSlide(): Promise<void> {
699+
async cleanSlide(targetPath: string): Promise<void> {
676700
const xml = await XmlHelper.getXmlFromArchive(
677701
this.targetArchive,
678-
this.targetPath,
702+
targetPath,
679703
);
680704

681705
this.unsupportedTags.forEach((tag) => {
@@ -685,7 +709,7 @@ export class Master implements IMaster {
685709
XmlHelper.sliceCollection(drop, 0);
686710
}
687711
});
688-
XmlHelper.writeXmlToArchive(this.targetArchive, this.targetPath, xml);
712+
XmlHelper.writeXmlToArchive(this.targetArchive, targetPath, xml);
689713
}
690714

691715
/**

src/dev.ts

Lines changed: 4 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -38,13 +38,11 @@ const run = async () => {
3838
.load('SlidesWithAdditionalMaster.pptx')
3939

4040
// We can disable .addMaster according to "autoImportSlideMasters: true"
41-
// .addMaster('SlidesWithAdditionalMaster.pptx', 1)
41+
// .addMaster('SlideMasters.pptx', 1)
4242

43-
.addSlide('SlideMasters.pptx', 3, (slide) => {
44-
// We can also disable "slide.useSlideLayout()"
45-
// with "autoImportSlideMasters: true"
46-
// slide.useSlideLayout();
47-
})
43+
.addSlide('SlideMasters.pptx', 1)
44+
.addSlide('SlideMasters.pptx', 2)
45+
.addSlide('SlideMasters.pptx', 3)
4846
.write(`add-slide-master-auto-import.test.pptx`);
4947
};
5048

src/helper/file-helper.ts

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -125,7 +125,11 @@ export class FileHelper {
125125
FileHelper.check(sourceArchive, sourceFile);
126126
contentTracker.trackFile(targetFile);
127127

128-
const content = await sourceArchive.read(sourceFile, 'nodebuffer');
128+
const content = await sourceArchive
129+
.read(sourceFile, 'nodebuffer')
130+
.catch((e) => {
131+
throw e;
132+
});
129133

130134
return targetArchive.write(targetFile || sourceFile, content);
131135
}

src/helper/xml-relationship-helper.ts

Lines changed: 36 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -4,10 +4,12 @@ import IArchive from '../interfaces/iarchive';
44
import { XmlHelper } from './xml-helper';
55
import { last, vd } from './general-helper';
66
import { ElementSubtype } from '../enums/element-type';
7+
import { FileHelper } from './file-helper';
78

89
export class XmlRelationshipHelper {
910
archive: IArchive;
1011
file: string;
12+
path: string;
1113
tag: string;
1214
xml: XmlDocument;
1315
xmlTargets: XmlElement[] = [];
@@ -21,21 +23,21 @@ export class XmlRelationshipHelper {
2123
return this;
2224
}
2325

24-
async initialize(archive: IArchive, file: string) {
26+
async initialize(archive: IArchive, file: string, path: string) {
2527
this.archive = archive;
2628
this.file = file;
29+
this.path = path + '/';
2730
const fileProxy = await this.archive;
28-
this.xml = await XmlHelper.getXmlFromArchive(fileProxy, this.file);
31+
this.xml = await XmlHelper.getXmlFromArchive(
32+
fileProxy,
33+
this.path + this.file,
34+
);
2935

3036
await this.readTargets();
3137

3238
return this;
3339
}
3440

35-
async writeArchive() {
36-
await XmlHelper.writeXmlToArchive(this.archive, this.file, this.xml);
37-
}
38-
3941
setXml(xml) {
4042
this.xml = xml;
4143
return this;
@@ -101,6 +103,30 @@ export class XmlRelationshipHelper {
101103
return this;
102104
}
103105

106+
async checkTargets(sourceArchive) {
107+
for (const xmlTarget of this.xmlTargets) {
108+
const targetFile = xmlTarget.getAttribute('Target');
109+
const targetPath = targetFile.replace('../', 'ppt/');
110+
111+
if (this.archive.fileExists(targetPath) === false) {
112+
console.error(
113+
'Relation target @' + this.file + ' does not exist: ' + targetPath,
114+
);
115+
116+
// This could be activated to assure all contents being available in
117+
// the target archive.
118+
119+
// await FileHelper.zipCopy(
120+
// sourceArchive,
121+
// targetPath,
122+
// this.archive,
123+
// targetPath + '.fixed',
124+
// );
125+
// xmlTarget.setAttribute('Target', targetFile + '.fixed');
126+
}
127+
}
128+
}
129+
104130
static parseRelationTarget(
105131
element: XmlElement,
106132
prefix?: string,
@@ -187,7 +213,8 @@ export class XmlRelationshipHelper {
187213
static async getSlideLayoutNumber(sourceArchive, slideId: number) {
188214
const slideToLayoutHelper = await new XmlRelationshipHelper().initialize(
189215
sourceArchive,
190-
`ppt/slides/_rels/slide${slideId}.xml.rels`,
216+
`slide${slideId}.xml.rels`,
217+
`ppt/slides/_rels`,
191218
);
192219
const slideToLayout = slideToLayoutHelper.getTargetsByPrefix(
193220
'../slideLayouts/slideLayout',
@@ -198,7 +225,8 @@ export class XmlRelationshipHelper {
198225
static async getSlideMasterNumber(sourceArchive, slideLayoutId: number) {
199226
const layoutToMasterHelper = await new XmlRelationshipHelper().initialize(
200227
sourceArchive,
201-
`ppt/slideLayouts/_rels/slideLayout${slideLayoutId}.xml.rels`,
228+
`slideLayout${slideLayoutId}.xml.rels`,
229+
`ppt/slideLayouts/_rels`,
202230
);
203231
const layoutToMaster = layoutToMasterHelper.getTargetsByPrefix(
204232
'../slideMasters/slideMaster',

src/shapes/image.ts

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -127,6 +127,12 @@ export class Image extends Shape implements IImage {
127127
await this.appendImageExtensionToContentType(this.extension);
128128
}
129129

130+
/**
131+
* ToDo: This will always append a new relation, and never replace an
132+
* existing relation. At the end of creation process, unused relations will
133+
* remain existing in the .xml.rels file. PowerPoint will not complain, but
134+
* integrity checks will not be valid by this.
135+
*/
130136
async appendToSlideRels(): Promise<HelperElement> {
131137
const targetRelFile = `ppt/${this.targetType}s/_rels/${this.targetType}${this.targetSlideNumber}.xml.rels`;
132138
this.createdRid = await XmlHelper.getNextRelId(

0 commit comments

Comments
 (0)