Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Feature: slide dimensions #84

Merged
merged 4 commits into from
Jan 12, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
46 changes: 46 additions & 0 deletions __tests__/get-slide-dimensions.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
import Automizer from '../src/automizer';

describe('Slide - Get Dimensions', () => {
it('retrieves correct dimensions for slides', async () => {
const automizer = new Automizer({
templateDir: `${__dirname}/../__tests__/pptx-templates`,
outputDir: `${__dirname}/../__tests__/pptx-output`,
removeExistingSlides: true
});

const pres = automizer
.loadRoot(`SlideDimensions1.pptx`)
.load(`SlideDimensions1.pptx`, '1')
.load(`SlideDimensions2.pptx`, '2');

let dimensions1Promise = new Promise((resolve, reject) => {
pres.addSlide('1', 1, async (slide) => {
try {
const dimensions = await slide.getDimensions();
resolve(dimensions);
} catch (error) {
reject(error);
}
});
});

let dimensions2Promise = new Promise((resolve, reject) => {
pres.addSlide('2', 1, async (slide) => {
try {
const dimensions = await slide.getDimensions();
resolve(dimensions);
} catch (error) {
reject(error);
}
});
});

const dimensions1 = await dimensions1Promise;
const dimensions2 = await dimensions2Promise;

expect(dimensions2).toEqual({ width: 9323387, height: 5670550 });
expect(dimensions1).toEqual({ width: 10080625, height: 6300787 });

await pres.write(`slideGetDimensionsTestOutput.pptx`);
});
});
Binary file added __tests__/pptx-templates/SlideDimensions1.pptx
Binary file not shown.
Binary file added __tests__/pptx-templates/SlideDimensions2.pptx
Binary file not shown.
14 changes: 13 additions & 1 deletion src/classes/has-shapes.ts
Original file line number Diff line number Diff line change
Expand Up @@ -164,6 +164,17 @@ export default class HasShapes {
return xmlSlideHelper.getAllElements(filterTags);
}

/**
* Asynchronously retrieves the dimensions of the slide.
* This function utilizes the XmlSlideHelper to get the slide dimensions.
*
* @returns {Promise<{width: number, height: number}>} A promise that resolves to an object containing the width and height of the slide.
*/
async getDimensions(): Promise<{ width: number; height: number }> {
const xmlSlideHelper = await this.getSlideHelper();
return xmlSlideHelper.getDimensions();
}

/**
* Asynchronously retrieves an instance of XmlSlideHelper for slide.
* @returns {Promise<XmlSlideHelper>} An instance of XmlSlideHelper.
Expand All @@ -175,8 +186,9 @@ export default class HasShapes {
this.sourceTemplate.archive,
this.sourcePath,
);

// Initialize the XmlSlideHelper
return new XmlSlideHelper(slideXml);
return new XmlSlideHelper(slideXml, this);
} catch (error) {
// Log the error message
throw new Error(error.message);
Expand Down
6 changes: 3 additions & 3 deletions src/dev.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,9 +13,9 @@ const run = async () => {
.load(`SlideWithCharts.pptx`, 'noCreationId');

pres.addSlide('noCreationId', 1, async (slide) => {
const elements = await slide.getAllElements();
const textElements = await slide.getAllTextElementIds();
vd(elements);
// const elements = await slide.getAllElements();
// const textElements = await slide.getAllTextElementIds();
vd(await slide.getDimensions());
});

pres.write(`myOutputPresentation.pptx`).then((summary) => {
Expand Down
57 changes: 54 additions & 3 deletions src/helper/xml-slide-helper.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import {
XmlElement,
} from '../types/xml-types';
import { XmlHelper } from './xml-helper';
import { vd } from './general-helper';
import HasShapes from '../classes/has-shapes';

export const nsMain =
'http://schemas.openxmlformats.org/presentationml/2006/main';
Expand All @@ -19,16 +19,19 @@ export const mapUriType = {
*/
export class XmlSlideHelper {
private slideXml: XmlDocument;
protected hasShapes: HasShapes;

/**
* Constructor for the XmlSlideHelper class.
* @param {XmlDocument} slideXml - The slide XML document to be used by the helper.
* @param hasShapes
*/
constructor(slideXml: XmlDocument) {
constructor(slideXml: XmlDocument, hasShapes?: HasShapes) {
if (!slideXml) {
throw Error('Slide XML is not defined');
}
this.slideXml = slideXml;
this.hasShapes = hasShapes;
}

getSlideCreationId(): number | undefined {
Expand Down Expand Up @@ -200,6 +203,54 @@ export class XmlSlideHelper {
element: XmlElement,
attributeName: string,
): number => {
return Number(element.getAttribute(attributeName));
return parseInt(element.getAttribute(attributeName), 10);
};

/**
* Asynchronously retrieves the dimensions of a slide.
* Tries to find the dimensions from the slide XML, then from the layout, master, and presentation XMLs in order.
*
* @returns {Promise<{ width: number, height: number }>} The dimensions of the slide.
* @throws Error if unable to determine dimensions.
*/
async getDimensions(): Promise<{ width: number; height: number }> {
try {
const dimensions = await this.getAndExtractDimensions(
'ppt/presentation.xml',
);
if (dimensions) return dimensions;
} catch (error) {
console.error(`Error while fetching slide dimensions: ${error}`);
throw error;
}
}

/**
* Fetches an XML file from the given path and extracts the dimensions.
*
* @param {string} path - The path of the XML file.
* @returns {Promise<{ width: number; height: number } | null>} - A promise that resolves with an object containing the width and height, or `null` if there was an error.
*/
getAndExtractDimensions = async (
path: string,
): Promise<{ width: number; height: number } | null> => {
try {
const xml = await XmlHelper.getXmlFromArchive(
this.hasShapes.sourceTemplate.archive,
path,
);
if (!xml) return null;

const sldSz = xml.getElementsByTagName('p:sldSz')[0];
if (sldSz) {
const width = XmlSlideHelper.parseCoordinate(sldSz, 'cx');
const height = XmlSlideHelper.parseCoordinate(sldSz, 'cy');
return { width, height };
}
return null;
} catch (error) {
console.warn(`Error while fetching XML from path ${path}: ${error}`);
return null;
}
};
}
4 changes: 4 additions & 0 deletions src/interfaces/islide.ts
Original file line number Diff line number Diff line change
Expand Up @@ -27,4 +27,8 @@ export interface ISlide {
useSlideLayout(targetLayout?: number | string): ISlide;
getAllElements(filterTags?: string[]): Promise<ElementInfo[]>;
getAllTextElementIds(): Promise<string[]>;
/**
* Asynchronously retrieves the dimensions of a slide.
*/
getDimensions(): Promise<{ width: number; height: number }>;
}
Loading