UNPKG

@vscode/gulp-electron

Version:
414 lines (348 loc) 11 kB
"use strict"; var path = require("path"); var plist = require("plist"); var es = require("event-stream"); var vfs = require("vinyl-fs"); var File = require("vinyl"); var rename = require("gulp-rename"); var semver = require("semver"); function getOriginalAppName(opts) { return semver.gte(opts.version, "0.24.0") ? "Electron" : "Atom"; } function getOriginalAppFullName(opts) { return getOriginalAppName(opts) + ".app"; } function getAppName(opts) { return (opts.productAppName || opts.productName) + ".app"; } exports.getAppPath = function (opts) { return getAppName(opts) + "/Contents/Resources/app"; }; function removeDefaultApp(opts) { var defaultAppPath = path.join( getOriginalAppFullName(opts), "Contents", "Resources", "default_app" ); return es.mapSync(function (f) { if (!f.relative.startsWith(defaultAppPath)) { return f; } }); } function patchIcon(opts) { if (!opts.darwinIcon) { return es.through(); } var resourcesPath = path.join( getOriginalAppFullName(opts), "Contents", "Resources" ); var iconName = semver.gte(opts.version, "0.24.0") ? "electron.icns" : "atom.icns"; var originalIconPath = path.join(resourcesPath, iconName); var iconPath = path.join(resourcesPath, opts.productName + ".icns"); var pass = es.through(); // filter out original icon var src = pass.pipe( es.mapSync(function (f) { if (f.relative !== originalIconPath) { return f; } }) ); // add custom icon var icon = vfs.src(opts.darwinIcon).pipe(rename(iconPath)); return es.duplex(pass, es.merge(src, icon)); } function patchInfoPlist(opts) { var contentsPath = path.join(getOriginalAppFullName(opts), "Contents"); var resourcesPath = path.join(contentsPath, "Resources"); var infoPlistPath = path.join(contentsPath, "Info.plist"); var didCloseIcons = false; var icons = es.through(); var input = es.through(); var output = input.pipe( es.map(function (f, cb) { if (f.relative !== infoPlistPath) { return cb(null, f); } var contents = ""; f.contents.on("error", function (err) { cb(err); }); f.contents.on("data", function (d) { contents += d; }); f.contents.on("end", function () { var infoPlist = plist.parse(contents.toString("utf8")); opts.darwinBundleIdentifier && (infoPlist["CFBundleIdentifier"] = opts.darwinBundleIdentifier); opts.darwinApplicationCategoryType && (infoPlist["LSApplicationCategoryType"] = opts.darwinApplicationCategoryType); infoPlist["CFBundleName"] = opts.productName; infoPlist["CFBundleDisplayName"] = opts.productDisplayName || opts.productName; infoPlist["CFBundleVersion"] = opts.productVersion; infoPlist["CFBundleShortVersionString"] = opts.productVersion; opts.copyright && (infoPlist["NSHumanReadableCopyright"] = opts.copyright); infoPlist["CFBundleIconFile"] = opts.productName + ".icns"; if (opts.darwinExecutable) { infoPlist["CFBundleExecutable"] = opts.darwinExecutable; } //Register the Application Help Book if it exists if (opts.darwinHelpBookFolder && opts.darwinHelpBookName) { infoPlist["CFBundleHelpBookFolder"] = opts.darwinHelpBookFolder; infoPlist["CFBundleHelpBookName"] = opts.darwinHelpBookName; } if (opts.darwinBundleDocumentTypes) { var iconsPaths = []; infoPlist["CFBundleDocumentTypes"] = ( infoPlist["CFBundleDocumentTypes"] || [] ).concat( opts.darwinBundleDocumentTypes.map(function (type) { iconsPaths.push(type.iconFile); var result = { CFBundleTypeName: type.name, CFBundleTypeRole: type.role, CFBundleTypeOSTypes: type.ostypes, CFBundleTypeExtensions: type.extensions, CFBundleTypeIconFile: path.basename(type.iconFile), }; if (type.utis) { result["LSItemContentTypes"] = type.utis; } return result; }) ); if (iconsPaths.length) { didCloseIcons = true; es.merge( iconsPaths.map(function (iconPath) { return vfs.src(iconPath).pipe( rename(function (path) { path.dirname = resourcesPath; }) ); }) ).pipe(icons); } } if (opts.darwinBundleURLTypes) { infoPlist["CFBundleURLTypes"] = opts.darwinBundleURLTypes.map( function (type) { return { CFBundleTypeRole: type.role, CFBundleURLName: type.name, CFBundleURLSchemes: type.urlSchemes, }; } ); } if (opts.darwinForceDarkModeSupport) { infoPlist["NSRequiresAquaSystemAppearance"] = false; } f.contents = Buffer.from(plist.build(infoPlist), "utf8"); cb(null, f); }); })) .pipe( es.through( null, function () { if (!didCloseIcons) { es.readArray([]).pipe(icons); } this.emit("end"); } ) ); return es.duplex(input, es.merge(output, icons)); } function createEntitlementsPlist(opts) { var input = es.through(); if (!opts.darwinEntitlements) { return input; } var contentsPath = path.join(getOriginalAppFullName(opts), "Contents"); var entitlementsPlistPath = path.join(contentsPath, "Entitlements.plist"); var result = {}; opts.darwinEntitlements.forEach((element) => { result[element] = true; }); var entitlementsFile = new File({ path: entitlementsPlistPath, contents: Buffer.from(plist.build(result)), }); return es.duplex(input, es.merge(input, es.readArray([entitlementsFile]))); } function patchHelperInfoPlist(opts) { var didCloseIcons = false; var icons = es.through(); var input = es.through(); var output = input.pipe( es.map(function (f, cb) { const match = /Contents\/Frameworks\/Electron\ Helper( \(\w+\))?\.app\/Contents\/Info.plist$/i.exec( f.relative); if (!match) { return cb(null, f); } var contents = ""; f.contents.on("error", function (err) { cb(err); }); f.contents.on("data", function (d) { contents += d; }); f.contents.on("end", function () { var infoPlist = plist.parse(contents.toString("utf8")); var suffix = match[1] ?? ""; if (opts.darwinBundleIdentifier) { infoPlist["CFBundleIdentifier"] = opts.darwinBundleIdentifier + ".helper"; } infoPlist["CFBundleName"] = `${opts.productName} Helper${suffix}`; if (infoPlist["CFBundleDisplayName"]) { infoPlist["CFBundleDisplayName"] = infoPlist["CFBundleName"]; } if (infoPlist["CFBundleExecutable"]) { infoPlist["CFBundleExecutable"] = infoPlist["CFBundleName"]; } f.contents = Buffer.from(plist.build(infoPlist), "utf8"); cb(null, f); }); })) .pipe( es.through( null, function () { if (!didCloseIcons) { es.readArray([]).pipe(icons); } this.emit("end"); } ) ); return es.duplex(input, es.merge(output, icons)); } function addCredits(opts) { if (!opts.darwinCredits) { return es.through(); } var creditsPath = path.join( getOriginalAppFullName(opts), "Contents", "Resources", "Credits.rtf" ); var input = es.through(); var credits; if (typeof opts.darwinCredits === "string") { credits = vfs.src(opts.darwinCredits).pipe(rename(creditsPath)); } else if (opts.darwinCredits instanceof Buffer) { credits = es.readArray([ new File({ path: creditsPath, contents: opts.darwinCredits, }), ]); } else { throw new Error("Unexpected value for darwinCredits"); } return es.duplex(input, es.merge(input, credits)); } function moveChromiumLicense(opts) { var newLicensePath = path.join( getOriginalAppFullName(opts), "Contents", "Resources" ); return es.mapSync(function (f) { if (!f.isNull() && !f.isDirectory() && f.path === "LICENSES.chromium.html") { f.dirname = newLicensePath; } return f; }); } function renameApp(opts) { var originalAppName = getOriginalAppName(opts); var originalAppNameRegexp = new RegExp("^" + getOriginalAppFullName(opts)); var appName = getAppName(opts); return rename(function (path) { // The app folder itself looks like a file if ( path.dirname === "." && path.basename === originalAppName && path.extname === ".app" ) { path.basename = opts.productAppName || opts.productName; } else { path.dirname = path.dirname.replace(originalAppNameRegexp, appName); } if ( /Contents\/MacOS$/.test(path.dirname) && path.basename === "Electron" && opts.darwinExecutable ) { path.basename = opts.darwinExecutable; } }); } function renameAppHelper(opts) { var originalAppName = getOriginalAppName(opts); var originalAppNameRegexp = new RegExp("^" + getOriginalAppFullName(opts)); var appName = getAppName(opts); var name = opts.productName; return rename(function (path) { var basenameMatch = /^Electron Helper( \(\w+\))?$/.exec(path.basename); if ( /Contents\/Frameworks/.test(path.dirname) && path.extname === ".app" && basenameMatch ) { var suffix = basenameMatch[1] || ""; path.basename = name + " Helper" + suffix; } else if ( /Contents\/Frameworks\/Electron\ Helper( \(\w+\))?\.app/.test( path.dirname ) ) { var isInMacOS = /Contents\/Frameworks\/Electron\ Helper( \(\w+\))?\.app\/Contents\/MacOS$/.test( path.dirname ); path.dirname = path.dirname.replace( /Electron\ Helper( \(\w+\))?\.app/, name + " Helper$1.app" ); if ( isInMacOS && /^Electron Helper( \(\w+\))?$/.test(path.basename) && path.extname === "" ) { path.basename = path.basename.replace( /Electron\ Helper( \(\w+\))?$/, name + " Helper$1" ); } } }); } exports.patch = function (opts) { var pass = es.through(); var src = pass .pipe(opts.keepDefaultApp ? es.through() : removeDefaultApp(opts)) .pipe(patchIcon(opts)) .pipe(patchInfoPlist(opts)) .pipe(patchHelperInfoPlist(opts)) .pipe(createEntitlementsPlist(opts)) .pipe(addCredits(opts)) .pipe(moveChromiumLicense(opts)) .pipe(renameApp(opts)) .pipe(renameAppHelper(opts)); return es.duplex(pass, src); };