UNPKG

@shockpkg/dir-projector

Version:

Package for creating Shockwave Director projectors

768 lines (614 loc) 15.7 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.ProjectorMacApp = void 0; var _path = require("path"); var _projector = require("../projector"); var _util = require("../util"); /** * ProjectorMacApp constructor. * * @param options Options object. */ class ProjectorMacApp extends _projector.Projector { /** * Binary name. * * @default null */ /** * Intel binary package, not universal binary. * * @default false */ /** * Icon file. * * @default null */ /** * Icon data. * * @default null */ /** * Info.plist file. * * @default null */ /** * Info.plist data. * * @default null */ /** * PkgInfo file. * * @default null */ /** * PkgInfo data. * * @default null */ /** * Nest Xtras at *.app/Contents/xtras. * * @default false */ constructor(options = {}) { super(options); this.binaryName = void 0; this.intel = void 0; this.iconFile = void 0; this.iconData = void 0; this.infoPlistFile = void 0; this.infoPlistData = void 0; this.pkgInfoFile = void 0; this.pkgInfoData = void 0; this.nestXtrasContents = void 0; this.binaryName = (0, _util.defaultNull)(options.binaryName); this.intel = (0, _util.defaultFalse)(options.intel); this.iconFile = (0, _util.defaultNull)(options.iconFile); this.iconData = (0, _util.defaultNull)(options.iconData); this.infoPlistFile = (0, _util.defaultNull)(options.infoPlistFile); this.infoPlistData = (0, _util.defaultNull)(options.infoPlistData); this.pkgInfoFile = (0, _util.defaultNull)(options.pkgInfoFile); this.pkgInfoData = (0, _util.defaultNull)(options.pkgInfoData); this.nestXtrasContents = (0, _util.defaultFalse)(options.nestXtrasContents); } /** * Projector file extension. * * @returns File extension. */ get projectorExtension() { return '.app'; } /** * Config file newline characters. * * @returns Newline characters. */ get configNewline() { return '\n'; } /** * Config file newline characters. * * @returns Newline characters. */ get lingoNewline() { return '\n'; } /** * Splash image file extension. * * @returns File extension. */ get splashImageExtension() { return '.pict'; } /** * If icon is specified. * * @returns Has icon. */ get hasIcon() { return !!(this.iconData || this.iconFile); } /** * If Info.plist is specified. * * @returns Has Info.plist. */ get hasInfoPlist() { return !!(this.infoPlistData || this.infoPlistFile); } /** * If PkgInfo is specified. * * @returns Has PkgInfo. */ get hasPkgInfo() { return !!(this.pkgInfoData || this.pkgInfoFile); } /** * Get the Projector Resources directory name. * * @returns Directory name. */ get projectorResourcesDirectoryName() { return this.intel ? 'Projector Intel Resources' : 'Projector Resources'; } /** * Get app binary name. * * @returns File name. */ get appBinaryName() { return this.appBinaryNameCustom || this.appBinaryNameDefault; } /** * Get app binary name, default. * * @returns File name. */ get appBinaryNameDefault() { return 'Projector'; } /** * Get app binary name, custom. * * @returns File name. */ get appBinaryNameCustom() { return this.binaryName; } /** * Get app icon name. * * @returns File name. */ get appIconName() { return this.appIconNameCustom || this.appIconNameDefault; } /** * Get app icon name, default. * * @returns File name. */ get appIconNameDefault() { return 'projector.icns'; } /** * Get app icon name, custom. * * @returns File name. */ get appIconNameCustom() { const n = this.binaryName; return n ? `${n}.icns` : null; } /** * Get app rsrc name. * * @returns File name. */ get appRsrcName() { return this.appRsrcNameCustom || this.appRsrcNameDefault; } /** * Get app rsrc name, default. * * @returns File name. */ get appRsrcNameDefault() { return 'Projector.rsrc'; } /** * Get app rsrc name, custom. * * @returns File name. */ get appRsrcNameCustom() { const n = this.binaryName; return n ? `${n}.rsrc` : null; } /** * Get app Info.plist path. * * @returns File path. */ get appPathInfoPlist() { return 'Contents/Info.plist'; } /** * Get app PkgInfo path. * * @returns File path. */ get appPathPkgInfo() { return 'Contents/PkgInfo'; } /** * Get app Frameworks path. * * @returns File path. */ get appPathFrameworks() { return 'Contents/Frameworks'; } /** * Get app Xtras path. * * @returns Directory path. */ get appPathXtras() { return `Contents/${this.xtrasDirectoryName}`; } /** * Get app binary path. * * @returns File path. */ get appPathBinary() { return this.appPathBinaryCustom || this.appPathBinaryDefault; } /** * Get app binary path, default. * * @returns File path. */ get appPathBinaryDefault() { return `Contents/MacOS/${this.appBinaryNameDefault}`; } /** * Get app binary path, custom. * * @returns File path. */ get appPathBinaryCustom() { const n = this.appBinaryNameCustom; return n ? `Contents/MacOS/${n}` : null; } /** * Get app icon path. * * @returns File path. */ get appPathIcon() { return this.appPathIconCustom || this.appPathIconDefault; } /** * Get app icon path, default. * * @returns File path. */ get appPathIconDefault() { return `Contents/Resources/${this.appIconNameDefault}`; } /** * Get app icon path, custom. * * @returns File path. */ get appPathIconCustom() { const n = this.appIconNameCustom; return n ? `Contents/Resources/${n}` : null; } /** * Get app rsrc path. * * @returns File path. */ get appPathRsrc() { return this.appPathRsrcCustom || this.appPathRsrcDefault; } /** * Get app rsrc path, default. * * @returns File path. */ get appPathRsrcDefault() { return `Contents/Resources/${this.appRsrcNameDefault}`; } /** * Get app rsrc path, custom. * * @returns File path. */ get appPathRsrcCustom() { const n = this.appRsrcNameCustom; return n ? `Contents/Resources/${n}` : null; } /** * Get icon data if any specified, from data or file. * * @returns Icon data or null. */ async getIconData() { return this._dataFromBufferOrFile(this.iconData, this.iconFile); } /** * Get Info.plist data if any specified, from data or file. * * @returns Info.plist data or null. */ async getInfoPlistData() { return this._dataFromValueOrFile(this.infoPlistData, this.infoPlistFile, '\n', 'utf8'); } /** * Get PkgInfo data if any specified, from data or file. * * @returns PkgInfo data or null. */ async getPkgInfoData() { return this._dataFromValueOrFile(this.pkgInfoData, this.pkgInfoFile, null, 'ascii'); } /** * Get the Xtras path. * * @param name Save name. * @returns Xtras path. */ getXtrasPath(name) { if (this.nestXtrasContents) { return `${name}/${this.appPathXtras}`; } return super.getXtrasPath(name); } /** * Get the icon path. * * @param name Save name. * @returns Icon path. */ getIconPath(name) { return `${name}/${this.appPathIcon}`; } /** * Get the Info.plist path. * * @param name Save name. * @returns Icon path. */ getInfoPlistPath(name) { return `${name}/${this.appPathInfoPlist}`; } /** * Get the PkgInfo path. * * @param name Save name. * @returns Icon path. */ getPkgInfoPath(name) { return `${name}/${this.appPathPkgInfo}`; } /** * Update XML code with customized variables. * * @param xml Plist code. * @param name Application name. * @returns Updated XML. */ updateInfoPlistCode(xml, name) { const { appBinaryNameCustom, appIconNameCustom } = this; if (appBinaryNameCustom) { xml = (0, _util.infoPlistReplace)(xml, 'CFBundleExecutable', (0, _util.plistStringTagEncode)(appBinaryNameCustom)); } if (appIconNameCustom) { xml = (0, _util.infoPlistReplace)(xml, 'CFBundleIconFile', (0, _util.plistStringTagEncode)(appIconNameCustom)); } xml = (0, _util.infoPlistReplace)(xml, 'CFBundleName', (0, _util.plistStringTagEncode)(this.getProjectorNameNoExtension(name))); return xml; } /** * Write out the projector. * * @param path Save path. * @param name Save name. */ async write(path, name) { await super.write(path, name); await this._writeIcon(path, name); await this._writePkgInfo(path, name); await this._writeInfoPlist(path, name); await this._updateInfoPlist(path, name); } /** * Write the projector skeleton from archive. * * @param path Save path. * @param name Save name. */ async _writeSkeleton(path, name) { const { hasIcon, hasInfoPlist, hasPkgInfo, shockwave, appPathInfoPlist, appPathPkgInfo, appPathFrameworks, appPathBinaryDefault, appPathBinaryCustom, appPathIconDefault, appPathIconCustom, appPathRsrcDefault, appPathRsrcCustom, xtrasDirectoryName, projectorResourcesDirectoryName } = this; const xtrasPath = this.getXtrasPath(name); const xtrasMappings = this.getIncludeXtrasMappings(); let foundProjectorResourcesDirectory = false; let foundFrameworks = false; let foundBinary = false; let foundInfoPlist = false; let foundPkgInfo = false; let foundIcon = false; let foundRsrc = false; let foundXtras = false; const xtrasHandler = async entry => { // Check if Xtras path. const xtrasRel = (0, _util.pathRelativeBase)(entry.volumePath, xtrasDirectoryName, true); if (xtrasRel === null) { return false; } foundXtras = true; // Find output path if being included, else skip. const dest = this.includeXtrasMappingsDest(xtrasMappings, xtrasRel); if (!dest) { return true; } await entry.extract((0, _path.join)(path, xtrasPath, dest)); return true; }; const projectorResourcesHandler = async entry => { // Check if projector path. const projectorRel = (0, _util.pathRelativeBase)(entry.volumePath, projectorResourcesDirectoryName, true); if (projectorRel === null) { return false; } foundProjectorResourcesDirectory = true; if ((0, _util.pathRelativeBaseMatch)(projectorRel, appPathFrameworks, true)) { foundFrameworks = true; // Exclude Frameworks directory for Shockwave projectors. if (shockwave) { return true; } } // Exclude Info.plist if using custom one. if ((0, _util.pathRelativeBaseMatch)(projectorRel, appPathInfoPlist, true)) { foundInfoPlist = true; if (hasInfoPlist) { return true; } } // Exclude PkgInfo if using custom one. if ((0, _util.pathRelativeBaseMatch)(projectorRel, appPathPkgInfo, true)) { foundPkgInfo = true; if (hasPkgInfo) { return true; } } let dest = projectorRel; // Possibly rename the binary. if ((0, _util.pathRelativeBaseMatch)(projectorRel, appPathBinaryDefault, true)) { foundBinary = true; if (appPathBinaryCustom) { dest = appPathBinaryCustom; } } // Special case for icon. if ((0, _util.pathRelativeBaseMatch)(projectorRel, appPathIconDefault, true)) { foundIcon = true; // Skip extracting icon if custom one. if (hasIcon) { return true; } // Possible rename the icon. if (appPathIconCustom) { dest = appPathIconCustom; } } // Special case for rsrc. if ((0, _util.pathRelativeBaseMatch)(projectorRel, appPathRsrcDefault, true)) { foundRsrc = true; if (appPathRsrcCustom) { dest = appPathRsrcCustom; } } await entry.extract((0, _path.join)(path, name, dest)); return true; }; const archive = await this.getSkeletonArchive(); await archive.read(async entry => { // Skip empty resource forks (every file in DMG). if ((0, _util.entryIsEmptyResourceFork)(entry)) { return; } if (await xtrasHandler(entry)) { return; } if (await projectorResourcesHandler(entry)) { return; } }); if (!foundProjectorResourcesDirectory) { throw new Error(`Failed to locate: ${projectorResourcesDirectoryName}`); } if (!foundFrameworks) { const d = projectorResourcesDirectoryName; throw new Error(`Failed to locate: ${d}/${appPathFrameworks}`); } if (!foundBinary) { const d = projectorResourcesDirectoryName; throw new Error(`Failed to locate: ${d}/${appPathBinaryDefault}`); } if (!foundInfoPlist) { const d = projectorResourcesDirectoryName; throw new Error(`Failed to locate: ${d}/${appPathInfoPlist}`); } if (!foundPkgInfo) {// Some projector skeletons lack this file. // const d = projectorResourcesDirectoryName; // throw new Error(`Failed to locate: ${d}/${appPathPkgInfo}`); } if (!foundIcon) { const d = projectorResourcesDirectoryName; throw new Error(`Failed to locate: ${d}/${appPathIconDefault}`); } if (!foundRsrc) { const d = projectorResourcesDirectoryName; throw new Error(`Failed to locate: ${d}/${appPathRsrcDefault}`); } if (!foundXtras) { throw new Error(`Failed to locate: ${xtrasDirectoryName}`); } } /** * Write out the projector icon file. * * @param path Save path. * @param name Save name. */ async _writeIcon(path, name) { await this._maybeWriteFile((await this.getIconData()), (0, _path.join)(path, this.getIconPath(name))); } /** * Write out the projector PkgInfo file. * * @param path Save path. * @param name Save name. */ async _writePkgInfo(path, name) { await this._maybeWriteFile((await this.getPkgInfoData()), (0, _path.join)(path, this.getPkgInfoPath(name))); } /** * Write out the projector Info.plist file. * * @param path Save path. * @param name Save name. */ async _writeInfoPlist(path, name) { await this._maybeWriteFile((await this.getInfoPlistData()), (0, _path.join)(path, this.getInfoPlistPath(name))); } /** * Update the projector Info.plist file fields. * * @param path Save path. * @param name Save name. */ async _updateInfoPlist(path, name) { const file = (0, _path.join)(path, this.getInfoPlistPath(name)); let data = await this._dataFromBufferOrFile(null, file); if (!data) { throw new Error('Failed to read Info.plist or updating'); } // Decode buffer, and update. const xmlOriginal = data.toString('utf8'); const xml = this.updateInfoPlistCode(xmlOriginal, name); // If unchanged, all done. if (xml === xmlOriginal) { return; } // Encode data and write. data = Buffer.from(xml, 'utf8'); await this._maybeWriteFile(data, (0, _path.join)(path, this.getInfoPlistPath(name))); } } exports.ProjectorMacApp = ProjectorMacApp; //# sourceMappingURL=macapp.js.map