UNPKG

@shockpkg/dir-projector

Version:

Package for creating Shockwave Director projectors

461 lines (421 loc) 9.6 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.ProjectorOtto = void 0; var _promises = require("node:fs/promises"); var _nodePath = require("node:path"); var _archiveFiles = require("@shockpkg/archive-files"); var _projector = require("../projector.js"); var _util = require("../util.js"); /** * Include Xtra mapping. */ /** * Include Xtra mapping, best match. */ /** * Include Xtras. */ /** * File patch. */ /** * ProjectorOtto object. */ class ProjectorOtto extends _projector.Projector { /** * Make a Shockwave projector. */ shockwave = false; /** * Splash image data. */ splashImageData = null; /** * Splash image file. */ splashImageFile = null; /** * Lingo data. */ lingoData = null; /** * Lingo file. */ lingoFile = null; /** * Xtras include map. */ includeXtras = null; /** * Nest xtras in a Configuration directory. */ nestXtrasConfiguration = false; /** * Skeleton path. */ skeleton = null; /** * Config data. */ configData = null; /** * Config file. */ configFile = null; /** * ProjectorOtto constructor. * * @param path Output path. */ constructor(path) { super(path); } /** * Config file extension. * * @returns File extension. */ get configExtension() { return '.INI'; } /** * Lingo file name. * * @returns File name. */ get lingoName() { return 'LINGO.INI'; } /** * Xtras directory name. * * @returns Directory encoding. */ get xtrasName() { return 'xtras'; } /** * Configuration directory name. * * @returns Directory encoding. */ get configurationName() { return 'Configuration'; } /** * Name of a projector trimming the extension, case insensitive. * * @returns Projector name without extension. */ get name() { return (0, _util.trimExtension)((0, _nodePath.dirname)(this.path), this.extension, true); } /** * Config file path. * * @returns Config path. */ get configPath() { const base = (0, _util.trimExtension)(this.path, this.extension, true); return `${base}${this.configExtension}`; } /** * Splash image file path. * * @returns Splash image path. */ get splashImagePath() { const base = (0, _util.trimExtension)(this.path, this.extension, true); return `${base}${this.splashImageExtension}`; } /** * Lingo file path. * * @returns Lingo file path. */ get lingoPath() { return (0, _nodePath.join)((0, _nodePath.dirname)(this.path), this.lingoName); } /** * Get outout Xtras path. * * @returns Output path. */ get xtrasPath() { const cn = this.configurationName; return this.nestXtrasConfiguration && cn ? (0, _nodePath.join)((0, _nodePath.dirname)(this.path), cn, this.xtrasName) : (0, _nodePath.join)((0, _nodePath.dirname)(this.path), this.xtrasName); } /** * Get config file data. * * @returns Config data or null. */ async getConfigData() { const { configData, configFile } = this; if (configData) { switch (typeof configData) { case 'function': { const d = await configData(); if (typeof d === 'string') { return new TextEncoder().encode(d); } if (Array.isArray(d)) { return new TextEncoder().encode(d.join(this.configNewline)); } return d; } case 'string': { return new TextEncoder().encode(configData); } default: { // Fall through. } } if (Array.isArray(configData)) { return new TextEncoder().encode(configData.join(this.configNewline)); } return configData; } if (configFile) { const d = await (0, _promises.readFile)(configFile); return new Uint8Array(d.buffer, d.byteOffset, d.byteLength); } return null; } /** * Get splash image data if any specified, from data or file. * * @returns Splash image data or null. */ async getSplashImageData() { const { splashImageData, splashImageFile } = this; if (splashImageData) { return typeof splashImageData === 'function' ? splashImageData() : splashImageData; } if (splashImageFile) { const d = await (0, _promises.readFile)(splashImageFile); return new Uint8Array(d.buffer, d.byteOffset, d.byteLength); } return null; } /** * Get lingo data if any specified, from data or file. * * @returns Lingo data or null. */ async getLingoData() { const { lingoData, lingoFile } = this; if (lingoData) { switch (typeof lingoData) { case 'function': { const d = await lingoData(); if (typeof d === 'string') { return new TextEncoder().encode(d); } if (Array.isArray(d)) { return new TextEncoder().encode(d.join(this.lingoNewline)); } return d; } case 'string': { return new TextEncoder().encode(lingoData); } default: { // Fall through. } } if (Array.isArray(lingoData)) { return new TextEncoder().encode(lingoData.join(this.lingoNewline)); } return lingoData; } if (lingoFile) { const d = await (0, _promises.readFile)(lingoFile); return new Uint8Array(d.buffer, d.byteOffset, d.byteLength); } return null; } /** * Get include Xtras as a list of mappings. * * @returns Mappings list. */ getIncludeXtrasMappings() { const { includeXtras } = this; const r = []; if (includeXtras) { for (const src of Object.keys(includeXtras)) { const dest = includeXtras[src]; r.push({ src, dest }); } } return r; } /** * Find the best match for a path in a list of Xtras mappings. * Path search is case-insensitive. * * @param mappings Mappings list. * @param path Path to search for. * @returns Best match or null. */ findIncludeXtrasMappingsBestMatch(mappings, path) { let best = null; let bestScore = -1; for (const map of mappings) { const { src } = map; const relative = src === '' ? path : (0, _util.pathRelativeBase)(path, src, true); if (relative === null || bestScore >= src.length) { continue; } best = { map, relative }; bestScore = src.length; } return best; } /** * Find output path for an Xtra. * * @param mappings Mappings list. * @param path Path to search for. * @returns Output path or null. */ includeXtrasMappingsDest(mappings, path) { const best = this.findIncludeXtrasMappingsBestMatch(mappings, path); if (!best) { return null; } const { map, relative } = best; const base = map.dest || map.src; // eslint-disable-next-line no-nested-ternary return base ? relative ? `${base}/${relative}` : base : relative; } /** * @inheritdoc */ async write() { const { skeleton } = this; if (!skeleton) { throw new Error('No projector skeleton configured'); } await this._checkOutput(); await this._writeSkeleton(skeleton); await this._writeConfig(); await this._writeSplashImage(); await this._writeLingo(); } /** * Check that output path is valid, else throws. */ async _checkOutput() { await Promise.all([this.path, this.configPath, this.splashImagePath, this.lingoPath].map(async p => { if (await (0, _archiveFiles.fsLstatExists)(p)) { throw new Error(`Output path already exists: ${p}`); } })); } /** * Write out the projector config file. */ async _writeConfig() { const data = await this.getConfigData(); if (data) { const { configPath } = this; await (0, _promises.mkdir)((0, _nodePath.dirname)(configPath), { recursive: true }); await (0, _promises.writeFile)(configPath, data); } } /** * Write out the projector splash image file. */ async _writeSplashImage() { const data = await this.getSplashImageData(); if (data) { const { splashImagePath } = this; await (0, _promises.mkdir)((0, _nodePath.dirname)(splashImagePath), { recursive: true }); await (0, _promises.writeFile)(splashImagePath, data); } } /** * Write out the projector lingo file. */ async _writeLingo() { const data = await this.getLingoData(); if (data) { const { lingoPath } = this; await (0, _promises.mkdir)((0, _nodePath.dirname)(lingoPath), { recursive: true }); await (0, _promises.writeFile)(lingoPath, data); } } /** * Projector file extension. * * @returns File extension. */ /** * Splash image file extension. * * @returns File extension. */ /** * Config file newline characters. * * @returns Newline characters. */ /** * Lingo file newline characters. * * @returns Newline characters. */ /** * Write the projector skeleton. * * @param skeleton Skeleton path. */ } exports.ProjectorOtto = ProjectorOtto; //# sourceMappingURL=otto.js.map