Skip to main content
Glama
automizer.js•19.8 kB
"use strict"; var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { if (k2 === undefined) k2 = k; var desc = Object.getOwnPropertyDescriptor(m, k); if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) { desc = { enumerable: true, get: function() { return m[k]; } }; } Object.defineProperty(o, k2, desc); }) : (function(o, m, k, k2) { if (k2 === undefined) k2 = k; o[k2] = m[k]; })); var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) { Object.defineProperty(o, "default", { enumerable: true, value: v }); }) : function(o, v) { o["default"] = v; }); var __importStar = (this && this.__importStar) || function (mod) { if (mod && mod.__esModule) return mod; var result = {}; if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k); __setModuleDefault(result, mod); return result; }; 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 }; }; Object.defineProperty(exports, "__esModule", { value: true }); const slide_1 = require("./classes/slide"); const template_1 = require("./classes/template"); const general_helper_1 = require("./helper/general-helper"); const master_1 = require("./classes/master"); const path_1 = __importDefault(require("path")); const fs = __importStar(require("fs")); const xml_helper_1 = require("./helper/xml-helper"); const modify_presentation_helper_1 = __importDefault(require("./helper/modify-presentation-helper")); const content_tracker_1 = require("./helper/content-tracker"); /** * Automizer * * The basic class for `pptx-automizer` package. * This class will be exported as `Automizer` by `index.ts`. */ class Automizer { /** * Creates an instance of `pptx-automizer`. * @param [params] */ constructor(params) { var _a, _b, _c, _d; /** * Templates of automizer * @internal */ this.templates = []; this.modifyPresentation = []; this.params = params; this.templateDir = (params === null || params === void 0 ? void 0 : params.templateDir) ? params.templateDir + '/' : ''; this.templateFallbackDir = (params === null || params === void 0 ? void 0 : params.templateFallbackDir) ? params.templateFallbackDir + '/' : ''; this.outputDir = (params === null || params === void 0 ? void 0 : params.outputDir) ? params.outputDir + '/' : ''; this.archiveParams = { mode: ((_a = params === null || params === void 0 ? void 0 : params.archiveType) === null || _a === void 0 ? void 0 : _a.mode) || 'jszip', baseDir: ((_b = params === null || params === void 0 ? void 0 : params.archiveType) === null || _b === void 0 ? void 0 : _b.baseDir) || __dirname + '/../cache', workDir: ((_c = params === null || params === void 0 ? void 0 : params.archiveType) === null || _c === void 0 ? void 0 : _c.workDir) || 'tmp', cleanupWorkDir: (_d = params === null || params === void 0 ? void 0 : params.archiveType) === null || _d === void 0 ? void 0 : _d.cleanupWorkDir, }; this.timer = Date.now(); this.setStatusTracker(params === null || params === void 0 ? void 0 : params.statusTracker); this.content = new content_tracker_1.ContentTracker(); if (params.rootTemplate) { const location = this.getLocation(params.rootTemplate, 'template'); this.rootTemplate = template_1.Template.import(location, this.archiveParams, this); } if (params.presTemplates) { this.params.presTemplates.forEach((file) => { const location = this.getLocation(file, 'template'); const archiveParams = Object.assign(Object.assign({}, this.archiveParams), { name: file }); const newTemplate = template_1.Template.import(location, archiveParams); this.templates.push(newTemplate); }); } } setStatusTracker(statusTracker) { const defaultStatusTracker = (status) => { console.log(status.info + ' (' + status.share + '%)'); }; this.status = { current: 0, max: 0, share: 0, info: undefined, increment: () => { this.status.current++; const nextShare = this.status.max > 0 ? Math.round((this.status.current / this.status.max) * 100) : 0; if (this.status.share !== nextShare) { this.status.share = nextShare; this.status.next(this.status); } }, next: statusTracker || defaultStatusTracker, }; } /** */ presentation() { var _a; return __awaiter(this, void 0, void 0, function* () { if (((_a = this.params) === null || _a === void 0 ? void 0 : _a.useCreationIds) === true) { yield this.setCreationIds(); } return this; }); } /** * Load a pptx file and set it as root template. * @param location - Filename or path to the template. Will be prefixed with 'templateDir' * @returns Instance of Automizer */ loadRoot(location) { return this.loadTemplate(location); } /** * Load a template pptx file. * @param location - Filename or path to the template. Will be prefixed with 'templateDir' * @param name - Optional: A short name for the template. If skipped, the template will be named by its location. * @returns Instance of Automizer */ load(location, name) { name = name === undefined ? location : name; return this.loadTemplate(location, name); } /** * Loads a pptx file either as a root template as a template file. * A name can be specified to give templates an alias. * @param location * @param [name] * @returns template */ loadTemplate(location, name) { location = this.getLocation(location, 'template'); const alreadyLoaded = this.templates.find((template) => template.name === name); if (alreadyLoaded) { return this; } const importParams = Object.assign(Object.assign({}, this.archiveParams), { name }); const newTemplate = template_1.Template.import(location, importParams, this); if (!this.isPresTemplate(newTemplate)) { this.rootTemplate = newTemplate; } else { this.templates.push(newTemplate); } return this; } /** * Load media files to output presentation. * @returns Instance of Automizer * @param filename Filename or path to the media file. * @param dir Specify custom path for media instead of mediaDir from AutomizerParams. */ loadMedia(filename, dir, prefix) { const files = general_helper_1.GeneralHelper.arrayify(filename); if (!this.rootTemplate) { throw "Can't load media, you need to load a root template first"; } files.forEach((file) => { const directory = dir || this.params.mediaDir; const filepath = path_1.default.join(directory, file); const extension = path_1.default .extname(file) .replace('.', ''); try { fs.accessSync(filepath, fs.constants.F_OK); } catch (e) { throw `Can't load media: ${filepath} does not exist.`; } this.rootTemplate.mediaFiles.push({ file, directory, filepath, extension, prefix, }); }); return this; } /** * Parses all loaded templates and collects creationIds for slides and * elements. This will make finding templates and elements independent * of slide number and element name. * @returns Promise<TemplateInfo[]> */ setCreationIds() { return __awaiter(this, void 0, void 0, function* () { const templateCreationId = []; for (const template of this.templates) { const creationIds = template.creationIds || (yield template.setCreationIds()); template.useCreationIds = this.params.useCreationIds; templateCreationId.push({ name: template.name, slides: creationIds, }); } return templateCreationId; }); } /** * Get some info about the imported templates * @returns Promise<PresentationInfo> */ getInfo() { return __awaiter(this, void 0, void 0, function* () { const creationIds = yield this.setCreationIds(); const info = { templateByName: (tplName) => { return creationIds.find((template) => template.name === tplName); }, slidesByTemplate: (tplName) => { var _a; return ((_a = info.templateByName(tplName)) === null || _a === void 0 ? void 0 : _a.slides) || []; }, slideByNumber: (tplName, slideNumber) => { return info .slidesByTemplate(tplName) .find((slide) => slide.number === slideNumber); }, elementByName: (tplName, slideNumber, elementName) => { var _a; return (_a = info .slideByNumber(tplName, slideNumber)) === null || _a === void 0 ? void 0 : _a.elements.find((element) => elementName === element.name); }, }; return info; }); } /** * Determines whether template is root or default template. * @param template * @returns pres template */ isPresTemplate(template) { return 'name' in template; } /** * Add a slide from one of the imported templates by slide number or creationId. * @param name - Name or alias of the template; must have been loaded with `Automizer.load()` * @param slideIdentifier - Number or creationId of slide in template presentation * @param callback - Executed after slide was added. The newly created slide will be passed to the callback as first argument. * @returns Instance of Automizer */ addSlide(name, slideIdentifier, callback) { if (this.rootTemplate === undefined) { throw new Error('You have to set a root template first.'); } const template = this.getTemplate(name); const newSlide = new slide_1.Slide({ presentation: this, template, slideIdentifier, }); if (this.params.autoImportSlideMasters) { newSlide.useSlideLayout(); } if (callback !== undefined) { newSlide.root = this; callback(newSlide); } this.rootTemplate.slides.push(newSlide); return this; } /** * Copy and modify a master and the associated layouts from template to output. * * @param name * @param sourceIdentifier * @param callback */ addMaster(name, sourceIdentifier, callback) { const key = sourceIdentifier + '@' + name; if (this.rootTemplate.masters.find((master) => master.key === key)) { console.log('Already imported ' + key); return this; } const template = this.getTemplate(name); const newMaster = new master_1.Master({ presentation: this, template, sourceIdentifier, }); if (callback !== undefined) { newMaster.root = this; callback(newMaster); } this.rootTemplate.masters.push(newMaster); return this; } /** * Searches this.templates to find template by given name. * @internal * @param name Alias name if given to loaded template. * @returns template */ getTemplate(name) { const template = this.templates.find((t) => t.name === name); if (template === undefined) { throw new Error(`Template not found: ${name}`); } return template; } /** * Write all imports and modifications to a file. * @param location - Filename or path for the file. Will be prefixed with 'outputDir' * @returns summary object. */ write(location) { return __awaiter(this, void 0, void 0, function* () { yield this.finalizePresentation(); yield this.rootTemplate.archive.output(this.getLocation(location, 'output'), this.params); const duration = (Date.now() - this.timer) / 600; return { status: 'finished', duration, file: location, filename: path_1.default.basename(location), templates: this.templates.length, slides: this.rootTemplate.count('slides'), charts: this.rootTemplate.count('charts'), images: this.rootTemplate.count('images'), masters: this.rootTemplate.count('masters'), }; }); } /** * Create a ReadableStream from output pptx file. * @param generatorOptions - JSZipGeneratorOptions for nodebuffer Output type * @returns Promise<NodeJS.ReadableStream> */ stream(generatorOptions) { return __awaiter(this, void 0, void 0, function* () { yield this.finalizePresentation(); if (!this.rootTemplate.archive.stream) { throw 'Streaming is not implemented for current archive type'; } return this.rootTemplate.archive.stream(this.params, generatorOptions); }); } /** * Pass final JSZip instance. * @returns Promise<NodeJS.ReadableStream> */ getJSZip() { return __awaiter(this, void 0, void 0, function* () { yield this.finalizePresentation(); if (!this.rootTemplate.archive.getFinalArchive) { throw 'GetFinalArchive is not implemented for current archive type'; } return this.rootTemplate.archive.getFinalArchive(); }); } finalizePresentation() { return __awaiter(this, void 0, void 0, function* () { yield this.writeMasterSlides(); yield this.writeSlides(); yield this.writeMediaFiles(); yield this.normalizePresentation(); yield this.applyModifyPresentationCallbacks(); // TODO: refactor content tracker, move this to root template content_tracker_1.contentTracker.reset(); }); } /** * Write all masterSlides to archive. */ writeMasterSlides() { return __awaiter(this, void 0, void 0, function* () { for (const slide of this.rootTemplate.masters) { yield this.rootTemplate.appendMasterSlide(slide); } }); } /** * Write all slides to archive. */ writeSlides() { return __awaiter(this, void 0, void 0, function* () { yield this.rootTemplate.countExistingSlides(); this.status.max = this.rootTemplate.slides.length; for (const slide of this.rootTemplate.slides) { yield this.rootTemplate.appendSlide(slide); } if (this.params.removeExistingSlides) { yield this.rootTemplate.truncate(); } }); } /** * Write all media files to archive. */ writeMediaFiles() { return __awaiter(this, void 0, void 0, function* () { for (const file of this.rootTemplate.mediaFiles) { const data = fs.readFileSync(file.filepath); let archiveFilename = 'ppt/media/' + file.file; if (file.prefix) { archiveFilename = 'ppt/media/' + file.prefix + file.file; } yield this.rootTemplate.archive.write(archiveFilename, data); yield xml_helper_1.XmlHelper.appendImageExtensionToContentType(this.rootTemplate.archive, file.extension); } }); } /** * Applies all callbacks in this.modifyPresentation-array. * The callback array can be pushed by this.modify() */ applyModifyPresentationCallbacks() { return __awaiter(this, void 0, void 0, function* () { yield xml_helper_1.XmlHelper.modifyXmlInArchive(this.rootTemplate.archive, `ppt/presentation.xml`, this.modifyPresentation); }); } /** * Apply some callbacks to restore archive/xml structure * and prevent corrupted pptx files. * * TODO: Use every imported image only once * TODO: Check for lost relations */ normalizePresentation() { return __awaiter(this, void 0, void 0, function* () { this.modify(modify_presentation_helper_1.default.normalizeSlideIds); this.modify(modify_presentation_helper_1.default.normalizeSlideMasterIds); if (this.params.cleanup) { if (this.params.removeExistingSlides) { this.modify(modify_presentation_helper_1.default.removeUnusedFiles); } this.modify(modify_presentation_helper_1.default.removedUnusedImages); this.modify(modify_presentation_helper_1.default.removeUnusedContentTypes); } }); } modify(cb) { this.modifyPresentation.push(cb); return this; } /** * Applies path prefix to given location string. * @param location path and/or filename * @param [type] template or output * @returns location */ getLocation(location, type) { switch (type) { case 'template': if (fs.existsSync(this.templateDir + location)) { return this.templateDir + location; } else if (fs.existsSync(this.templateFallbackDir + location)) { return this.templateFallbackDir + location; } else { (0, general_helper_1.vd)('No file matches "' + location + '"'); (0, general_helper_1.vd)('@templateDir: ' + this.templateDir); (0, general_helper_1.vd)('@templateFallbackDir: ' + this.templateFallbackDir); } break; case 'output': return this.outputDir + location; default: return location; } } } exports.default = Automizer; //# sourceMappingURL=automizer.js.map

Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/guangxiangdebizi/PPT-MCP'

If you have feedback or need assistance with the MCP directory API, please join our Discord server