pptx-automizer
Version:
A template based pptx generator
207 lines • 9.64 kB
JavaScript
"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());
});
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.Image = void 0;
const file_helper_1 = require("../helper/file-helper");
const xml_helper_1 = require("../helper/xml-helper");
const shape_1 = require("../classes/shape");
const element_type_1 = require("../enums/element-type");
const constants_1 = require("../constants/constants");
class Image extends shape_1.Shape {
constructor(shape, targetType) {
super(shape, targetType);
this.sourceFile = shape.target.file.replace('../media/', '');
this.extension = file_helper_1.FileHelper.getFileExtension(this.sourceFile);
this.relAttribute = 'r:embed';
this.relType =
'http://schemas.openxmlformats.org/officeDocument/2006/relationships/image';
// A shape retrieved by Image.getAllOnSlide() can also be (nested) SVG.
if (!shape.sourceMode && this.extension === 'svg') {
shape.sourceMode = 'image:svg';
}
switch (shape.sourceMode) {
case 'image:svg':
this.relRootTag = constants_1.TargetByRelIdMap['image:svg'].relRootTag;
this.relParent = (element) => element.parentNode;
break;
case 'image:media':
case 'image:audioFile':
case 'image:videoFile':
this.relRootTag = constants_1.TargetByRelIdMap[shape.sourceMode].relRootTag;
this.relAttribute = constants_1.TargetByRelIdMap[shape.sourceMode].relAttribute;
this.relType = constants_1.TargetByRelIdMap[shape.sourceMode].relType;
this.relParent = (element) => element.parentNode;
break;
default:
this.relRootTag = 'a:blip';
this.relParent = (element) => element.parentNode.parentNode;
break;
}
}
/*
* It is necessary to update existing rIds for all
* unmodified images on an added slide at first.
*/
modifyOnAddedSlide(targetTemplate, targetSlideNumber) {
return __awaiter(this, void 0, void 0, function* () {
yield this.prepare(targetTemplate, targetSlideNumber);
yield this.updateElementsRelId();
return this;
});
}
modify(targetTemplate, targetSlideNumber) {
return __awaiter(this, void 0, void 0, function* () {
yield this.prepare(targetTemplate, targetSlideNumber);
yield this.setTargetElement();
yield this.updateTargetElementRelId();
this.applyImageCallbacks();
yield this.replaceIntoSlideTree();
return this;
});
}
append(targetTemplate, targetSlideNumber) {
return __awaiter(this, void 0, void 0, function* () {
yield this.prepare(targetTemplate, targetSlideNumber);
yield this.setTargetElement();
yield this.updateTargetElementRelId();
yield this.appendToSlideTree();
this.applyImageCallbacks();
yield this.processImageRelations(targetTemplate, targetSlideNumber);
return this;
});
}
/**
* For audio/video and svg, some more relations need to be handled.
*/
processImageRelations(targetTemplate, targetSlideNumber) {
return __awaiter(this, void 0, void 0, function* () {
/*
* SVG images require a corresponding PNG image.
*/
if (this.hasSvgBlipRelation()) {
yield this.processRelatedContent(targetTemplate, targetSlideNumber, 'image:svg');
}
/**
* Media files are children of images with additional relations
*/
if (this.hasAudioRelation()) {
yield this.processRelatedMediaContent(targetTemplate, targetSlideNumber, 'image:audioFile');
}
if (this.hasVideoRelation()) {
yield this.processRelatedMediaContent(targetTemplate, targetSlideNumber, 'image:videoFile');
}
});
}
processRelatedMediaContent(targetTemplate, targetSlideNumber, sourceMode) {
return __awaiter(this, void 0, void 0, function* () {
yield this.processRelatedContent(targetTemplate, targetSlideNumber, 'image:media');
yield this.processRelatedContent(targetTemplate, targetSlideNumber, sourceMode);
});
}
processRelatedContent(targetTemplate, targetSlideNumber, sourceMode) {
return __awaiter(this, void 0, void 0, function* () {
const relsPath = `ppt/slides/_rels/slide${this.sourceSlideNumber}.xml.rels`;
const target = yield xml_helper_1.XmlHelper.getTargetByRelId(this.sourceArchive, relsPath, this.targetElement, sourceMode);
yield new Image({
mode: 'append',
target,
sourceArchive: this.sourceArchive,
sourceSlideNumber: this.sourceSlideNumber,
type: element_type_1.ElementType.Image,
sourceMode,
}, this.targetType).modifyMediaRelation(targetTemplate, targetSlideNumber, this.targetElement);
});
}
modifyMediaRelation(targetTemplate, targetSlideNumber, targetElement) {
return __awaiter(this, void 0, void 0, function* () {
yield this.prepare(targetTemplate, targetSlideNumber);
this.targetElement = targetElement;
yield this.updateTargetElementRelId();
return this;
});
}
/*
* Apply all ShapeModificationCallbacks to target element.
* Third argument this.createdRelation is necessery to directly
* manipulate relation Target and change the image.
*/
applyImageCallbacks() {
this.applyCallbacks(this.callbacks, this.targetElement, this.createdRelation);
}
remove(targetTemplate, targetSlideNumber) {
return __awaiter(this, void 0, void 0, function* () {
yield this.prepare(targetTemplate, targetSlideNumber);
yield this.removeFromSlideTree();
return this;
});
}
prepare(targetTemplate, targetSlideNumber) {
return __awaiter(this, void 0, void 0, function* () {
yield this.setTarget(targetTemplate, targetSlideNumber);
this.targetNumber = this.targetTemplate.incrementCounter('images');
this.targetFile = this.getTargetFileName();
yield this.copyFiles();
yield this.appendTypes();
yield this.appendToSlideRels();
});
}
copyFiles() {
return __awaiter(this, void 0, void 0, function* () {
yield file_helper_1.FileHelper.zipCopy(this.sourceArchive, `ppt/media/${this.sourceFile}`, this.targetArchive, `ppt/media/${this.targetFile}`);
});
}
getTargetFileName() {
const targetFileType = this.target.file.includes('media')
? 'media'
: 'image';
return targetFileType + this.targetNumber + '.' + this.extension;
}
appendTypes() {
return __awaiter(this, void 0, void 0, function* () {
yield this.appendImageExtensionToContentType(this.extension);
});
}
/**
* ToDo: This will always append a new relation, and never replace an
* existing relation. At the end of creation process, unused relations will
* remain existing in the .xml.rels file. PowerPoint will not complain, but
* integrity checks will not be valid by this.
*/
appendToSlideRels() {
return __awaiter(this, void 0, void 0, function* () {
const targetRelFile = `ppt/${this.targetType}s/_rels/${this.targetType}${this.targetSlideNumber}.xml.rels`;
this.createdRid = yield xml_helper_1.XmlHelper.getNextRelId(this.targetArchive, targetRelFile);
const targetFileName = this.getTargetFileName();
const attributes = {
Id: this.createdRid,
Type: this.relType,
Target: `../media/${targetFileName}`,
};
this.createdRelation = yield xml_helper_1.XmlHelper.append(xml_helper_1.XmlHelper.createRelationshipChild(this.targetArchive, targetRelFile, attributes));
});
}
hasSvgBlipRelation() {
return this.targetElement.getElementsByTagName('asvg:svgBlip').length > 0;
}
hasAudioRelation() {
return this.targetElement.getElementsByTagName('a:audioFile').length > 0;
}
hasVideoRelation() {
return this.targetElement.getElementsByTagName('a:videoFile').length > 0;
}
static getAllOnSlide(archive, relsPath) {
return __awaiter(this, void 0, void 0, function* () {
return yield xml_helper_1.XmlHelper.getTargetsByRelationshipType(archive, relsPath, 'http://schemas.openxmlformats.org/officeDocument/2006/relationships/image');
});
}
}
exports.Image = Image;
//# sourceMappingURL=image.js.map