mirror of https://github.com/jiahaog/Nativefier
158 lines
5.4 KiB
TypeScript
158 lines
5.4 KiB
TypeScript
import * as fs from 'fs';
|
|
import * as crypto from 'crypto';
|
|
import * as path from 'path';
|
|
import { promisify } from 'util';
|
|
|
|
import { kebabCase } from 'lodash';
|
|
import * as log from 'loglevel';
|
|
|
|
import { copyFileOrDir } from '../helpers/helpers';
|
|
import { AppOptions } from '../options/model';
|
|
|
|
const writeFileAsync = promisify(fs.writeFile);
|
|
|
|
/**
|
|
* Only picks certain app args to pass to nativefier.json
|
|
*/
|
|
function pickElectronAppArgs(options: AppOptions): any {
|
|
return {
|
|
alwaysOnTop: options.nativefier.alwaysOnTop,
|
|
appCopyright: options.packager.appCopyright,
|
|
appVersion: options.packager.appVersion,
|
|
backgroundColor: options.nativefier.backgroundColor,
|
|
basicAuthPassword: options.nativefier.basicAuthPassword,
|
|
basicAuthUsername: options.nativefier.basicAuthUsername,
|
|
bounce: options.nativefier.bounce,
|
|
browserwindowOptions: options.nativefier.browserwindowOptions,
|
|
buildVersion: options.packager.buildVersion,
|
|
clearCache: options.nativefier.clearCache,
|
|
counter: options.nativefier.counter,
|
|
crashReporter: options.nativefier.crashReporter,
|
|
darwinDarkModeSupport: options.packager.darwinDarkModeSupport,
|
|
disableContextMenu: options.nativefier.disableContextMenu,
|
|
disableDevTools: options.nativefier.disableDevTools,
|
|
disableGpu: options.nativefier.disableGpu,
|
|
diskCacheSize: options.nativefier.diskCacheSize,
|
|
enableEs3Apis: options.nativefier.enableEs3Apis,
|
|
fastQuit: options.nativefier.fastQuit,
|
|
fileDownloadOptions: options.nativefier.fileDownloadOptions,
|
|
flashPluginDir: options.nativefier.flashPluginDir,
|
|
fullScreen: options.nativefier.fullScreen,
|
|
globalShortcuts: options.nativefier.globalShortcuts,
|
|
height: options.nativefier.height,
|
|
hideWindowFrame: options.nativefier.hideWindowFrame,
|
|
ignoreCertificate: options.nativefier.ignoreCertificate,
|
|
ignoreGpuBlacklist: options.nativefier.ignoreGpuBlacklist,
|
|
insecure: options.nativefier.insecure,
|
|
internalUrls: options.nativefier.internalUrls,
|
|
maxHeight: options.nativefier.maxHeight,
|
|
maximize: options.nativefier.maximize,
|
|
maxWidth: options.nativefier.maxWidth,
|
|
minHeight: options.nativefier.minHeight,
|
|
minWidth: options.nativefier.minWidth,
|
|
name: options.packager.name,
|
|
nativefierVersion: options.nativefier.nativefierVersion,
|
|
processEnvs: options.nativefier.processEnvs,
|
|
proxyRules: options.nativefier.proxyRules,
|
|
showMenuBar: options.nativefier.showMenuBar,
|
|
singleInstance: options.nativefier.singleInstance,
|
|
targetUrl: options.packager.targetUrl,
|
|
titleBarStyle: options.nativefier.titleBarStyle,
|
|
tray: options.nativefier.tray,
|
|
userAgent: options.nativefier.userAgent,
|
|
versionString: options.nativefier.versionString,
|
|
width: options.nativefier.width,
|
|
win32metadata: options.packager.win32metadata,
|
|
x: options.nativefier.x,
|
|
y: options.nativefier.y,
|
|
zoom: options.nativefier.zoom,
|
|
};
|
|
}
|
|
|
|
async function maybeCopyScripts(srcs: string[], dest: string): Promise<void> {
|
|
if (!srcs || srcs.length === 0) {
|
|
log.debug('No files to inject, skipping copy.');
|
|
return;
|
|
}
|
|
|
|
log.debug(`Copying ${srcs.length} files to inject in app.`);
|
|
for (const src of srcs) {
|
|
if (!fs.existsSync(src)) {
|
|
throw new Error(
|
|
`File ${src} not found. Note that Nativefier expects *local* files, not URLs.`,
|
|
);
|
|
}
|
|
|
|
let destFileName: string;
|
|
if (path.extname(src) === '.js') {
|
|
destFileName = 'inject.js';
|
|
} else if (path.extname(src) === '.css') {
|
|
destFileName = 'inject.css';
|
|
} else {
|
|
return;
|
|
}
|
|
|
|
const destPath = path.join(dest, 'inject', destFileName);
|
|
log.debug(`Copying injection file "${src}" to "${destPath}"`);
|
|
await copyFileOrDir(src, destPath);
|
|
}
|
|
}
|
|
|
|
function normalizeAppName(appName: string, url: string): string {
|
|
// use a simple 3 byte random string to prevent collision
|
|
const hash = crypto.createHash('md5');
|
|
hash.update(url);
|
|
const postFixHash = hash.digest('hex').substring(0, 6);
|
|
const normalized = kebabCase(appName.toLowerCase());
|
|
return `${normalized}-nativefier-${postFixHash}`;
|
|
}
|
|
|
|
function changeAppPackageJsonName(
|
|
appPath: string,
|
|
name: string,
|
|
url: string,
|
|
): void {
|
|
const packageJsonPath = path.join(appPath, '/package.json');
|
|
const packageJson = JSON.parse(fs.readFileSync(packageJsonPath).toString());
|
|
const normalizedAppName = normalizeAppName(name, url);
|
|
packageJson.name = normalizedAppName;
|
|
log.debug(`Updating ${packageJsonPath} 'name' field to ${normalizedAppName}`);
|
|
|
|
fs.writeFileSync(packageJsonPath, JSON.stringify(packageJson));
|
|
}
|
|
|
|
/**
|
|
* Creates a temporary directory, copies the './app folder' inside,
|
|
* and adds a text file with the app configuration.
|
|
*/
|
|
export async function prepareElectronApp(
|
|
src: string,
|
|
dest: string,
|
|
options: AppOptions,
|
|
): Promise<void> {
|
|
log.debug(`Copying electron app from ${src} to ${dest}`);
|
|
try {
|
|
await copyFileOrDir(src, dest);
|
|
} catch (err) {
|
|
throw `Error copying electron app from ${src} to temp dir ${dest}. Error: ${err}`;
|
|
}
|
|
|
|
const appJsonPath = path.join(dest, '/nativefier.json');
|
|
log.debug(`Writing app config to ${appJsonPath}`);
|
|
await writeFileAsync(
|
|
appJsonPath,
|
|
JSON.stringify(pickElectronAppArgs(options)),
|
|
);
|
|
|
|
try {
|
|
await maybeCopyScripts(options.nativefier.inject, dest);
|
|
} catch (err) {
|
|
log.error('Error copying injection files.', err);
|
|
}
|
|
changeAppPackageJsonName(
|
|
dest,
|
|
options.packager.name,
|
|
options.packager.targetUrl,
|
|
);
|
|
}
|