#!/usr/bin/env python import os import zipfile import re import plistlib import shutil import json from os.path import join def xp_filename(basename): return re.sub('["<>*?|\\\\]', "_", basename.replace("/", "-").replace(":", ".")) def versionify(version): return ".".join(filter(lambda x: x.isdigit(), re.split("[-+.]", version))[:3]) def main(nwdir, nwpackage): if not os.path.isdir(nwdir): raise StandardError("input (%r) is not a directory" % nwdir) nwzip = zipfile.ZipFile(nwpackage) icnss = filter(lambda f: f.lower().endswith(".icns"), nwzip.namelist()) package = json.load(nwzip.open("package.json")) app = join(nwdir, "nwjs.app") title = package["window"]["title"] exe = package["name"].split(".")[-1] plist = dict( CFBundleDisplayName=title, CFBundleExecutable=exe, CFBundleIdentifier=package["name"], CFBundleInfoDictionaryVersion="6.0", CFBundleName=title, CFBundlePackageType="APPL", CFBundleShortVersionString=package["version"], CFBundleIconFile="nw.icns", CFBundleVersion=versionify(package["version"]), LSMinimumSystemVersion="10.6.0", NSPrincipalClass="NSApplication", NSSupportsAutomaticGraphicsSwitching=True, ) if icnss: icnss.sort() os.remove(join(app, "Contents", "Resources", "nw.icns")) nwzip.extract(icnss[0], join(app, "Contents", "Resources")) plist["CFBundleIconFile"] = icnss[0] plistlib.writePlist(plist, join(app, "Contents/Info.plist")) exedir = join(app, "Contents", "MacOS") shutil.move(join(exedir, "nwjs"), join(exedir, exe)) shutil.copy(nwpackage, join(app, "Contents", "Resources", "app.nw")) shutil.move(app, join(app, "..", xp_filename(title) + ".app")) if __name__ == "__main__": import sys main(*sys.argv[1:])