UNPKG

@shockpkg/dir-projector

Version:

Package for creating Shockwave Director projectors

377 lines (295 loc) 8.13 kB
"use strict"; var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault"); var _interopRequireWildcard = require("@babel/runtime/helpers/interopRequireWildcard"); Object.defineProperty(exports, "__esModule", { value: true }); exports.defaultValue = defaultValue; exports.defaultNull = defaultNull; exports.defaultFalse = defaultFalse; exports.defaultTrue = defaultTrue; exports.entryIsEmptyResourceFork = entryIsEmptyResourceFork; exports.pathRelativeBase = pathRelativeBase; exports.pathRelativeBaseMatch = pathRelativeBaseMatch; exports.trimExtension = trimExtension; exports.xmlEntitiesEncode = xmlEntitiesEncode; exports.xmlEntitiesDecode = xmlEntitiesDecode; exports.plistStringTagEncode = plistStringTagEncode; exports.plistStringTagDecode = plistStringTagDecode; exports.infoPlistReplace = infoPlistReplace; exports.infoPlistRead = infoPlistRead; exports.rcedit = rcedit; var _archiveFiles = require("@shockpkg/archive-files"); var entities = _interopRequireWildcard(require("entities")); var _rcedit2 = _interopRequireDefault(require("rcedit")); var _sax = _interopRequireDefault(require("sax")); // @ts-ignore // Handle module loader differences between CJS and ESM. const decodeXML = entities.decodeXML || entities.default.decodeXML; const encodeXML = entities.encodeXML || entities.default.encodeXML; /** * Default value if value is undefined. * * @param value Value. * @param defaultValue Default value. * @returns Value or the default value if undefined. */ function defaultValue(value, defaultValue) { // eslint-disable-next-line no-undefined return value === undefined ? defaultValue : value; } /** * Default null if value is undefined. * * @param value Value. * @returns Value or null if undefined. */ function defaultNull(value) { return defaultValue(value, null); } /** * Default false if value is undefined. * * @param value Value. * @returns Value or false if undefined. */ function defaultFalse(value) { return defaultValue(value, false); } /** * Default true if value is undefined. * * @param value Value. * @returns Value or true if undefined. */ function defaultTrue(value) { return defaultValue(value, true); } /** * Check if Archive Entry is empty resource fork. * * @param entry Archive Entry. * @returns Is empty resource fork. */ function entryIsEmptyResourceFork(entry) { return entry.type === _archiveFiles.PathType.RESOURCE_FORK && !entry.size; } /** * Find path relative from base, if base matches. * * @param path Path to match against. * @param start Search start. * @param nocase Match case-insensitive. * @returns Returns path, or null. */ function pathRelativeBase(path, start, nocase = false) { const p = nocase ? path.toLowerCase() : path; const s = nocase ? start.toLowerCase() : start; if (p === s) { return ''; } if (p.startsWith(`${s}/`)) { return path.substr(s.length + 1); } return null; } /** * Same as pathRelativeBase, but retuns true on a match, else false. * * @param path Path to match against. * @param start Search start. * @param nocase Match case-insensitive. * @returns Returns true on match, else false. */ function pathRelativeBaseMatch(path, start, nocase = false) { const p = nocase ? path.toLowerCase() : path; const s = nocase ? start.toLowerCase() : start; if (p === s) { return true; } if (p.startsWith(`${s}/`)) { return true; } return false; } /** * Trim a file extenion. * * @param path File path. * @param ext File extension. * @param nocase Match case-insensitive. * @returns Path without file extension. */ function trimExtension(path, ext, nocase = false) { const p = nocase ? path.toLowerCase() : path; const e = nocase ? ext.toLowerCase() : ext; return p.endsWith(e) ? path.substr(0, p.length - e.length) : path; } /** * Encode string for XML. * * @param value String value. * @returns Escaped string. */ function xmlEntitiesEncode(value) { return encodeXML(value); } /** * Decode string for XML. * * @param value Encoded value. * @returns Decoded string. */ function xmlEntitiesDecode(value) { return decodeXML(value); } /** * Encode string into plist string tag. * * @param value String value. * @returns Plist string. */ function plistStringTagEncode(value) { return `<string>${xmlEntitiesEncode(value)}</string>`; } /** * Decode string from plist string tag. * * @param xml XML tag. * @returns Plain string, or null. */ function plistStringTagDecode(xml) { const start = '<string>'; const end = '</string>'; if (!xml.startsWith(start) || !xml.endsWith(end)) { return null; } const contents = xml.substring(start.length, xml.length - end.length); return xmlEntitiesDecode(contents); } /** * A small helper function for finding Info.plist values. * * @param xml XML string. * @param key Plist dict key. * @returns Found indexes or null. */ function infoPlistFind(xml, key) { let replaceTagStart = -1; let replaceTagEnd = -1; const parser = _sax.default.parser(true, {}); // Get the tag path in a consistent way. const tagPath = () => { const tags = [...parser.tags]; const { tag } = parser; if (tag && tags[tags.length - 1] !== tag) { tags.push(tag); } return tags.map(o => o.name); }; const dictTag = () => { const path = tagPath(); if (path.length !== 3 || path[0] !== 'plist' || path[1] !== 'dict') { return null; } return path[2]; }; let keyTag = false; let nextTag = false; // eslint-disable-next-line @typescript-eslint/unbound-method parser.onerror = err => { throw err; }; // eslint-disable-next-line @typescript-eslint/unbound-method parser.ontext = text => { if (keyTag && text === key) { nextTag = true; } }; // eslint-disable-next-line @typescript-eslint/unbound-method parser.onopentag = node => { const tag = dictTag(); if (!tag) { return; } if (tag === 'key') { keyTag = true; return; } if (!nextTag) { return; } if (replaceTagStart < 0) { replaceTagStart = parser.startTagPosition - 1; } }; // eslint-disable-next-line @typescript-eslint/unbound-method parser.onclosetag = node => { const tag = dictTag(); if (!tag) { return; } if (tag === 'key') { keyTag = false; return; } if (!nextTag) { return; } nextTag = false; if (replaceTagEnd < 0) { replaceTagEnd = parser.position; } }; parser.write(xml).close(); return replaceTagStart < 0 || replaceTagEnd < 0 ? null : [replaceTagStart, replaceTagEnd]; } /** * A small utility function for replacing Info.plist values. * * @param xml XML string. * @param key Plist dict key. * @param value Plist dict value, XML tag. * @returns Updated document. */ function infoPlistReplace(xml, key, value) { const found = infoPlistFind(xml, key); if (!found) { return xml; } // Splice in new value. const before = xml.substr(0, found[0]); const after = xml.substr(found[1]); return `${before}${value}${after}`; } /** * A small utility function for reading Info.plist values. * * @param xml XML string. * @param key Plist dict key. * @returns XML tag. */ function infoPlistRead(xml, key) { const found = infoPlistFind(xml, key); return found ? xml.substring(found[0], found[1]) : null; } /** * Uses rcedit to edit the resources of a Windows EXE. * Requires either Windows or wine in the path. * * @param path File path. * @param options Options object. */ async function rcedit(path, options) { const opts = {}; if (options.iconPath) { opts.icon = options.iconPath; } if (typeof options.fileVersion === 'string') { opts['file-version'] = options.fileVersion; } if (typeof options.productVersion === 'string') { opts['product-version'] = options.productVersion; } if (options.versionStrings) { opts['version-string'] = options.versionStrings; } await (0, _rcedit2.default)(path, opts); } //# sourceMappingURL=util.js.map