UNPKG

pptx-automizer

Version:

A template based pptx generator

153 lines 8.32 kB
"use strict"; var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); } return new (P || (P = Promise))(function (resolve, reject) { function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); } step((generator = generator.apply(thisArg, _arguments || [])).next()); }); }; var __importDefault = (this && this.__importDefault) || function (mod) { return (mod && mod.__esModule) ? mod : { "default": mod }; }; var _a; Object.defineProperty(exports, "__esModule", { value: true }); const types_1 = require("../types/types"); const slugify_1 = __importDefault(require("slugify")); const image_size_1 = require("image-size"); const fs_1 = __importDefault(require("fs")); const xml_helper_1 = require("./xml-helper"); const compute_src_rect_1 = require("./compute-src-rect"); class ModifyImageHelper { } _a = ModifyImageHelper; /** * Update the "Target" attribute of a created image relation. * This will change the image itself. Load images with Automizer.loadMedia * @param filename name of target image in root template media folder. */ ModifyImageHelper.setRelationTarget = (filename) => { return (element, arg1) => { arg1.setAttribute('Target', xml_helper_1.XmlHelper.sanitizeAttr('../media/' + (0, slugify_1.default)(filename))); }; }; /** * Update the "Target" attribute of a created image relation. * This will change the image itself. Load images with Automizer.loadMedia * This will also auto-crop the image to the new width and height, * based on the container aspect ratio, derived from the original image * and using the new image width and height based on the files loaded into * the presentation media folder using .loadMedia() * @param filename name of target image in root template media folder. * @param pres presentation properties (to access the root template archive) */ ModifyImageHelper.setRelationTargetCover = (filename, pres) => { return (element, arg1) => __awaiter(void 0, void 0, void 0, function* () { const newTarget = '../media/' + (0, slugify_1.default)(filename); const originalTarget = arg1.getAttribute('Target'); const originalTargetPath = originalTarget.replace('../', 'ppt/'); const originalImageDimensions = { width: 100, height: 100 }; const newImageDimensions = { width: 100, height: 100 }; // Get the new image dimensions, using the rootTemplate mediafiles array, // since we have it loaded into the presentation media folder using .loadMedia() // If we don't find the media file, we warn, but continue try { const mediaFile = pres.rootTemplate.mediaFiles.find((file) => file.file === filename); if (!mediaFile) { throw new Error('Media file not found in template archive in path: ' + filename); } const buffer = (0, types_1.getMediaBuffer)(mediaFile, fs_1.default.readFileSync); const _dimensions = (0, image_size_1.imageSize)(buffer); newImageDimensions.width = _dimensions.width; newImageDimensions.height = _dimensions.height; } catch (error) { console.warn("Couldn't find media file in template archive in path."); } // Find the original image dimensions using the original target path from the original slide // using the rootTemplate archive file system and get the image dimensions. // If we don't find the original image, we warn, but continue // If we find the original image, we get the image dimensions and use this to reverse calculate // the aspect ratio and then use the new image dimensions to calculate and set the new crop on srcRect. // This results in the image being cropped in the image container to match the aspect ratio of the new image. try { if (pres.rootTemplate.archive.fileExists(originalTargetPath)) { const originalImage = yield pres.rootTemplate.archive.read(originalTargetPath, 'nodebuffer'); const _dimensions = (0, image_size_1.imageSize)(originalImage); originalImageDimensions.width = _dimensions.width; originalImageDimensions.height = _dimensions.height; } else { throw new Error('Original image not found from template archive in path: ' + originalTargetPath); } const srcRect = element.getElementsByTagName('a:srcRect')[0]; const srcRectLeft = srcRect.getAttribute('l'); const srcRectTop = srcRect.getAttribute('t'); const srcRectRight = srcRect.getAttribute('r'); const srcRectBottom = srcRect.getAttribute('b'); const currentSrcRect = { l: srcRectLeft ? Number(srcRectLeft) : 0, t: srcRectTop ? Number(srcRectTop) : 0, r: srcRectRight ? Number(srcRectRight) : 0, b: srcRectBottom ? Number(srcRectBottom) : 0, }; const containerAr = (0, compute_src_rect_1.inferContainerAr)(originalImageDimensions.width, originalImageDimensions.height, currentSrcRect); const newSrcRect = (0, compute_src_rect_1.computeSrcRectForNewImage)(containerAr, newImageDimensions.width, newImageDimensions.height); srcRect.setAttribute('l', String(newSrcRect.l)); srcRect.setAttribute('t', String(newSrcRect.t)); srcRect.setAttribute('r', String(newSrcRect.r)); srcRect.setAttribute('b', String(newSrcRect.b)); } catch (error) { const errorMessage = error instanceof Error ? error.message : String(error); console.warn('Skipped setting relation target cropped due to an error: ' + errorMessage); } arg1.setAttribute('Target', xml_helper_1.XmlHelper.sanitizeAttr(newTarget)); }); }; /* Update an existing duotone image overlay element (WIP) Apply a duotone color to an image p:blipFill -> a:blip fill element. Works best on white icons, see __tests__/media/feather.png */ ModifyImageHelper.setDuotoneFill = (duotoneParams) => (element) => { const blipFill = element.getElementsByTagName('p:blipFill'); if (!blipFill) { return; } const duotone = blipFill.item(0).getElementsByTagName('a:duotone')[0]; if (duotone) { if (duotoneParams === null || duotoneParams === void 0 ? void 0 : duotoneParams.color) { const srgbClr = duotone.getElementsByTagName('a:srgbClr')[0]; if (srgbClr) { // Only sRgb supported srgbClr.setAttribute('val', String(duotoneParams.color.value)); if ((duotoneParams === null || duotoneParams === void 0 ? void 0 : duotoneParams.tint) !== undefined) { // tint needs to be 0 - 100000 const tint = srgbClr.getElementsByTagName('a:tint')[0]; if (tint) { tint.setAttribute('val', String(duotoneParams.tint)); } } if ((duotoneParams === null || duotoneParams === void 0 ? void 0 : duotoneParams.satMod) !== undefined) { const satMod = srgbClr.getElementsByTagName('a:satMod')[0]; if (satMod) { satMod.setAttribute('val', String(duotoneParams.satMod)); } } } } if (duotoneParams === null || duotoneParams === void 0 ? void 0 : duotoneParams.prstClr) { const prstClr = duotone.getElementsByTagName('a:prstClr')[0]; if (prstClr) { // Only tested with "black" and "white" prstClr.setAttribute('val', String(duotoneParams.prstClr)); } } } }; exports.default = ModifyImageHelper; //# sourceMappingURL=modify-image-helper.js.map