Skip to content

Commit 386ad47

Browse files
committed
feat(pres): remove slides from presentation's slide list
1 parent 01529c2 commit 386ad47

File tree

7 files changed

+110
-17
lines changed

7 files changed

+110
-17
lines changed

__tests__/remove-slides.test.ts

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
import Automizer from '../src/automizer';
2+
import ModifyPresentationHelper from '../src/helper/modify-presentation-helper';
3+
4+
test('Remove slides while and after modifying.', async () => {
5+
const automizer = new Automizer({
6+
templateDir: `${__dirname}/pptx-templates`,
7+
outputDir: `${__dirname}/pptx-output`,
8+
});
9+
10+
const pres = automizer
11+
.loadRoot(`RootTemplate.pptx`)
12+
.load(`EmptySlide.pptx`, 'empty')
13+
.load(`SlideWithCharts.pptx`, 'charts')
14+
.load(`SlideWithImages.pptx`, 'images');
15+
16+
pres
17+
.addSlide('charts', 2, (slide) => {})
18+
.addSlide('images', 2, (slide) => {
19+
// Pass the current slide index to remove a slide.
20+
slide.remove(3);
21+
// You can as well remove another slide.
22+
slide.remove(1);
23+
})
24+
.addSlide('empty', 1, (slide) => {})
25+
.addSlide('empty', 1, (slide) => {})
26+
.addSlide('images', 1, (slide) => {
27+
// Calling
28+
slide.remove(1);
29+
});
30+
31+
// Eventually remove some slides.
32+
pres.modify(ModifyPresentationHelper.removeSlides([1, 3]));
33+
34+
const result = await pres.write(`remove-slides.test.pptx`);
35+
36+
// ToDo: decrement counter
37+
expect(result.slides).toBe(6);
38+
});

src/automizer.ts

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,6 @@ import { ISlide } from './interfaces/islide';
2828
import { IMaster } from './interfaces/imaster';
2929
import { ContentTypeExtension } from './enums/content-type-map';
3030
import slugify from 'slugify';
31-
import PptxGenJS from 'pptxgenjs';
3231

3332
/**
3433
* Automizer

src/classes/has-shapes.ts

Lines changed: 23 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -425,15 +425,12 @@ export default class HasShapes {
425425
// For hyperlinks, we need to handle them differently
426426
if (info.target) {
427427
await new Hyperlink(
428-
info,
429-
this.targetType,
428+
info,
429+
this.targetType,
430430
this.sourceArchive,
431431
info.target.isExternal ? 'external' : 'internal',
432-
info.target.file
433-
)[info.mode](
434-
this.targetTemplate,
435-
this.targetNumber
436-
);
432+
info.target.file,
433+
)[info.mode](this.targetTemplate, this.targetNumber);
437434
}
438435
break;
439436
default:
@@ -803,7 +800,7 @@ export default class HasShapes {
803800
sourceArchive: this.sourceArchive,
804801
sourceSlideNumber: this.sourceNumber,
805802
},
806-
this.targetType
803+
this.targetType,
807804
).modifyOnAddedSlide(this.targetTemplate, this.targetNumber);
808805
}
809806

@@ -816,11 +813,14 @@ export default class HasShapes {
816813
sourceArchive: this.sourceArchive,
817814
sourceSlideNumber: this.sourceNumber,
818815
},
819-
this.targetType
816+
this.targetType,
820817
).modifyOnAddedSlide(this.targetTemplate, this.targetNumber);
821818
}
822819

823-
const oleObjects = await OLEObject.getAllOnSlide(this.sourceArchive, this.relsPath);
820+
const oleObjects = await OLEObject.getAllOnSlide(
821+
this.sourceArchive,
822+
this.relsPath,
823+
);
824824
for (const oleObject of oleObjects) {
825825
await new OLEObject(
826826
{
@@ -830,12 +830,15 @@ export default class HasShapes {
830830
sourceSlideNumber: this.sourceNumber,
831831
},
832832
this.targetType,
833-
this.sourceArchive
833+
this.sourceArchive,
834834
).modifyOnAddedSlide(this.targetTemplate, this.targetNumber, oleObjects);
835835
}
836836

837837
// Copy hyperlinks
838-
const hyperlinks = await Hyperlink.getAllOnSlide(this.sourceArchive, this.relsPath);
838+
const hyperlinks = await Hyperlink.getAllOnSlide(
839+
this.sourceArchive,
840+
this.relsPath,
841+
);
839842
for (const hyperlink of hyperlinks) {
840843
// Create a new hyperlink with the correct target information
841844
const hyperlinkInstance = new Hyperlink(
@@ -848,14 +851,18 @@ export default class HasShapes {
848851
this.targetType,
849852
this.sourceArchive,
850853
hyperlink.isExternal ? 'external' : 'internal',
851-
hyperlink.file
854+
hyperlink.file,
852855
);
853-
856+
854857
// Ensure the target property is properly set
855858
hyperlinkInstance.target = hyperlink;
856-
859+
857860
// Process the hyperlink
858-
await hyperlinkInstance.modifyOnAddedSlide(this.targetTemplate, this.targetNumber, hyperlinks);
861+
await hyperlinkInstance.modifyOnAddedSlide(
862+
this.targetTemplate,
863+
this.targetNumber,
864+
hyperlinks,
865+
);
859866
}
860867
}
861868

src/classes/slide.ts

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ import { XmlRelationshipHelper } from '../helper/xml-relationship-helper';
99
import { IMaster } from '../interfaces/imaster';
1010
import HasShapes from './has-shapes';
1111
import { Master } from './master';
12+
import ModifyPresentationHelper from '../helper/modify-presentation-helper';
1213

1314
export class Slide extends HasShapes implements ISlide {
1415
targetType: ShapeTargetType = 'slide';
@@ -226,4 +227,13 @@ export class Slide extends HasShapes implements ISlide {
226227
`ppt/slides/_rels/slide${this.targetNumber}.xml.rels`,
227228
);
228229
}
230+
231+
/**
232+
* Remove a slide from presentation's slide list.
233+
* ToDo: Find the current count for this slide;
234+
* ToDo: this.targetNumber is undefined at this point.
235+
*/
236+
remove(slide: number): void {
237+
this.root.modify(ModifyPresentationHelper.removeSlides([slide]));
238+
}
229239
}

src/helper/modify-presentation-helper.ts

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,20 @@ export default class ModifyPresentationHelper {
2727
XmlHelper.sortCollection(slides, order);
2828
};
2929

30+
/**
31+
* Pass an array of slide numbers to remove from slide sortation.
32+
* @order Array of slide numbers, starting by 1
33+
*/
34+
static removeSlides = (numbers: number[]) => (xml: XmlDocument) => {
35+
const slides = ModifyPresentationHelper.getSlidesCollection(xml);
36+
numbers.map((index, i) => numbers[i]--);
37+
for (let i = 0; i <= slides.length; i++) {
38+
if (numbers.includes(i)) {
39+
XmlHelper.remove(slides[i]);
40+
}
41+
}
42+
};
43+
3044
/**
3145
* Set ids to prevent corrupted pptx.
3246
* Must start with 256 and increment by one.

src/interfaces/ipresentation-props.ts

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,8 @@ import { AutomizerParams, StatusTracker } from '../types/types';
22
import { PresTemplate } from './pres-template';
33
import { RootPresTemplate } from './root-pres-template';
44
import { ContentTracker } from '../helper/content-tracker';
5+
import { ModifyXmlCallback } from '../types/xml-types';
6+
import Automizer from '../automizer';
57

68
export interface IPresentationProps {
79
rootTemplate: RootPresTemplate;
@@ -10,5 +12,8 @@ export interface IPresentationProps {
1012
timer: number;
1113
status?: StatusTracker;
1214
content?: ContentTracker;
15+
1316
getTemplate(name: string): PresTemplate;
17+
18+
modify(cb: ModifyXmlCallback): Automizer;
1419
}

src/interfaces/islide.ts

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,9 +13,13 @@ import { ElementInfo } from '../types/xml-types';
1313
export interface ISlide {
1414
sourceArchive: IArchive;
1515
sourceNumber: SourceIdentifier;
16+
1617
modify(callback: SlideModificationCallback): void;
18+
1719
modifyRelations(callback: SlideModificationCallback): void;
20+
1821
append(targetTemplate: RootPresTemplate): Promise<void>;
22+
1923
/**
2024
* Add an element from one of the loaded templates to this slide.
2125
* @param presName Filename or custom name of source template
@@ -29,6 +33,7 @@ export interface ISlide {
2933
selector: FindElementSelector,
3034
callback?: ModificationCallback | ModificationCallback[],
3135
): ISlide;
36+
3237
/**
3338
* Modify an element on the current slide.
3439
* @param selector The name or element creationID of the element on current slide
@@ -38,24 +43,39 @@ export interface ISlide {
3843
selector: FindElementSelector,
3944
callback: ModificationCallback | ModificationCallback[],
4045
): ISlide;
46+
4147
/**
4248
* Use PptxGenJs to generate a new element from scratch on this slide.
4349
* @param generate Pass a callback to create an element on current slide
4450
* @param objectName Give a custom name for this element or automizer will create a random uuid
4551
*/
4652
generate(generate: GenerateOnSlideCallback, objectName?: string): ISlide;
53+
4754
/**
4855
* You can remove an element on the current slide.
4956
* @param selector Pass element name or creationId to find target element.
5057
*/
5158
removeElement(selector: FindElementSelector): ISlide;
59+
5260
useSlideLayout(targetLayout?: number | string): ISlide;
61+
5362
getElement(selector: FindElementSelector): Promise<ElementInfo>;
63+
5464
getAllElements(filterTags?: string[]): Promise<ElementInfo[]>;
65+
5566
getAllTextElementIds(): Promise<string[]>;
67+
5668
getGeneratedElements(): GenerateElements[];
69+
5770
/**
5871
* Asynchronously retrieves the dimensions of a slide.
5972
*/
6073
getDimensions(): Promise<{ width: number; height: number }>;
74+
75+
/**
76+
* Remove a slide from output. The slide will be calculated, but
77+
* eventually withdrawn from slide list.
78+
* Slide number starts by 1.
79+
*/
80+
remove(number: number): void;
6181
}

0 commit comments

Comments
 (0)