Skip to content

Commit 1d915d7

Browse files
committed
feat(layout): improved placeholder matching if old and new layout gets merged
1 parent 6ea681d commit 1d915d7

File tree

12 files changed

+868
-211
lines changed

12 files changed

+868
-211
lines changed

src/classes/has-shapes.ts

Lines changed: 58 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@ import {
2525
ElementInfo,
2626
RelationshipAttribute,
2727
SlideListAttribute,
28+
TemplateSlideInfo,
2829
XmlDocument,
2930
XmlElement,
3031
} from '../types/xml-types';
@@ -175,14 +176,18 @@ export default class HasShapes {
175176

176177
/**
177178
* Asynchronously retrieves all elements from the slide.
178-
* @params filterTags Use an array of strings to filter parent tags (e.g. 'sp')
179+
* @param filterTags Use an array of strings to filter parent tags (e.g. 'sp')
180+
* @param slideInfo Use placeholder position from layout as fallback
179181
* @returns {Promise<ElementInfo[]>} A promise that resolves to an array of ElementInfo objects.
180182
*/
181-
async getAllElements(filterTags?: string[]): Promise<ElementInfo[]> {
183+
async getAllElements(
184+
filterTags?: string[],
185+
slideInfo?: TemplateSlideInfo,
186+
): Promise<ElementInfo[]> {
182187
const xmlSlideHelper = await this.getSlideHelper();
183188

184189
// Get all ElementInfo objects
185-
return xmlSlideHelper.getAllElements(filterTags);
190+
return xmlSlideHelper.getAllElements(filterTags, slideInfo);
186191
}
187192

188193
/**
@@ -218,8 +223,17 @@ export default class HasShapes {
218223
this.sourcePath,
219224
);
220225

226+
const sourceLayoutId = await XmlRelationshipHelper.getSlideLayoutNumber(
227+
this.sourceTemplate.archive,
228+
this.sourceNumber,
229+
);
230+
221231
// Initialize the XmlSlideHelper
222-
return new XmlSlideHelper(slideXml, this);
232+
return new XmlSlideHelper(slideXml, {
233+
sourceArchive: this.sourceTemplate.archive,
234+
slideNumber: this.sourceNumber,
235+
sourceLayoutId
236+
});
223237
} catch (error) {
224238
// Log the error message
225239
throw new Error(error.message);
@@ -352,29 +366,53 @@ export default class HasShapes {
352366
});
353367
}
354368

355-
getAlreadyModifiedElement(selector: FindElementSelector) {
356-
// Check if an element with the same selector is already imported in modify mode
357-
const existingElement = this.importElements.find((element) => {
369+
/**
370+
* Checks if an element with the same selector has already been imported or modified.
371+
* This function helps to apply placeholder modifications properly.
372+
*
373+
* @param {FindElementSelector} selector - The selector used to identify an element.
374+
* Can be a string or an object with name and optional creationId/nameIdx.
375+
* @returns {ImportElement|undefined} The existing element if found, otherwise undefined.
376+
*/
377+
getAlreadyModifiedElement(
378+
selector: FindElementSelector,
379+
): ImportElement | undefined {
380+
// Search through previously imported/modified elements
381+
return this.importElements.find((element) => {
382+
// Skip comparison if either selector is not an object
358383
if (
359384
typeof selector !== 'object' ||
360385
typeof element.selector !== 'object'
361386
) {
362-
return;
387+
return false;
363388
}
364389

390+
// Case 1: Element without creationId - match by name and nameIdx
365391
if (!selector.creationId) {
366-
// Match by name and nameIdx only if the shape has no creationId
367-
return selector.name === element.selector.name && selector.nameIdx === element.selector.nameIdx;
368-
} else if (selector.creationId && element.selector?.creationId) {
369-
const creaId1 = selector.creationId.replace('{', '').replace('}', '');
370-
const creaId2 = element.selector.creationId
371-
.replace('{', '')
372-
.replace('}', '');
373-
374-
return selector.name === element.selector.name && creaId1 === creaId2;
392+
return (
393+
selector.name === element.selector.name &&
394+
selector.nameIdx === element.selector.nameIdx
395+
);
375396
}
397+
398+
// Case 2: Element with creationId - match by name and normalized creationId
399+
if (selector.creationId && element.selector?.creationId) {
400+
// Normalize creationIds by removing curly braces
401+
const normalizedSelectorId = selector.creationId.replace(/{|}/g, '');
402+
const normalizedElementId = element.selector.creationId.replace(
403+
/{|}/g,
404+
'',
405+
);
406+
407+
return (
408+
selector.name === element.selector.name &&
409+
normalizedSelectorId === normalizedElementId
410+
);
411+
}
412+
413+
// No match found for this element
414+
return false;
376415
});
377-
return existingElement;
378416
}
379417

380418
/**
@@ -565,7 +603,7 @@ export default class HasShapes {
565603
selector: selector,
566604
});
567605
} else {
568-
if(selector.creationId) {
606+
if (selector.creationId) {
569607
strategies.push({
570608
mode: 'findByElementCreationId',
571609
selector: selector.creationId,
@@ -575,7 +613,7 @@ export default class HasShapes {
575613
strategies.push({
576614
mode: 'findByElementName',
577615
selector: selector.name,
578-
nameIdx: selector.nameIdx
616+
nameIdx: selector.nameIdx,
579617
});
580618
}
581619

0 commit comments

Comments
 (0)