UNPKG

electron-html-to

Version:

Convert html to html/image using electron

331 lines (257 loc) 9.01 kB
'use strict'; var util = require('util'), // disabling import rule because `electron` is a built-in module // eslint-disable-next-line import/no-unresolved electron = require('electron'), sliced = require('sliced'), assign = require('object-assign'), getBrowserWindowOpts = require('./getBrowserWindowOpts'), listenRequestsInPage = require('./listenRequestsInPage'), conversionScript = require('./conversionScript'), evaluate = require('./evaluateJS'), parentChannel = require('../ipc')(process), app = electron.app, renderer = electron.ipcMain, BrowserWindow = electron.BrowserWindow; var windows = [], electronVersion = undefined, log = undefined, WORKER_ID = undefined, DEBUG_MODE = undefined, CHROME_COMMAND_LINE_SWITCHES = undefined, ALLOW_LOCAL_FILES_ACCESS = undefined, MAX_LOG_ENTRY_SIZE = undefined; WORKER_ID = process.env.ELECTRON_WORKER_ID; DEBUG_MODE = Boolean(process.env.ELECTRON_HTML_TO_DEBUGGING); CHROME_COMMAND_LINE_SWITCHES = JSON.parse(process.env.chromeCommandLineSwitches); ALLOW_LOCAL_FILES_ACCESS = process.env.allowLocalFilesAccess === 'true'; MAX_LOG_ENTRY_SIZE = parseInt(process.env.maxLogEntrySize, 10); if (process.versions.electron) { electronVersion = process.versions.electron; } else if (process.versions['atom-shell']) { electronVersion = process.versions['atom-shell']; } else { electronVersion = ''; } if (isNaN(MAX_LOG_ENTRY_SIZE)) { MAX_LOG_ENTRY_SIZE = 1000; } log = function () { // eslint-disable-next-line prefer-rest-params var newArgs = sliced(arguments); newArgs.unshift('[Worker ' + WORKER_ID + ']'); parentChannel.emit.apply(parentChannel, ['log'].concat(newArgs)); }; global.windowsData = {}; global.windowsLogs = {}; Object.keys(CHROME_COMMAND_LINE_SWITCHES).forEach(function (switchName) { var switchValue = CHROME_COMMAND_LINE_SWITCHES[switchName]; if (switchValue != null) { log('establishing chrome command line switch [' + switchName + ':' + switchValue + ']'); app.commandLine.appendSwitch(switchName, switchValue); } else { log('establishing chrome command line switch [' + switchName + ']'); app.commandLine.appendSwitch(switchName); } }); if (app.dock && typeof app.dock.hide === 'function') { if (!DEBUG_MODE) { app.dock.hide(); } } app.on('window-all-closed', function () { // by default dont close the app (because the electron ipc will be running) // only close when debug mode is on if (DEBUG_MODE) { app.quit(); } }); app.on('ready', function () { log('electron process ready..'); renderer.on('page-error', function (ev, windowId, errMsg, errStack) { // saving errors on page saveLogsInStore(global.windowsLogs[windowId], 'warn', 'error in page: ' + errMsg); saveLogsInStore(global.windowsLogs[windowId], 'warn', 'error in page stack: ' + errStack); parentChannel.emit('page-error', windowId, errMsg, errStack); }); renderer.on('page-log', function (ev, args) { var windowId = args[0], logLevel = args[1], logArgs = args.slice(2), // removing log level argument newArgs = args.slice(0, 1).concat(logArgs); // saving logs saveLogsInStore(global.windowsLogs[windowId], logLevel, logArgs, true); parentChannel.emit.apply(parentChannel, ['page-log'].concat(newArgs)); }); renderer.on('log', function () { // eslint-disable-next-line prefer-rest-params var newArgs = sliced(arguments), windowId = newArgs.splice(0, 2)[1]; newArgs.unshift('[Browser window - ' + windowId + ' log ]:'); log.apply(log, newArgs); }); // communication with electron-workers ipc process.on('message', function (data) { if (!data) { return; } function respondIpc(err, payload) { var msg = { workerEvent: 'taskResponse', taskId: data.taskId }; if (err) { // err.message is lost when serialized, so we need to explicitly set it msg.error = assign({}, err); msg.error.message = err.message; } else { msg.response = payload; } process.send(msg); } if (data.workerEvent === 'ping') { process.send({ workerEvent: 'pong' }); } else if (data.workerEvent === 'task') { log('new task for electron-ipc..'); try { createBrowserWindow(respondIpc, data.payload); } catch (uncaughtErr) { respondIpc(uncaughtErr); } } }); }); function createBrowserWindow(respondIpc, settingsData) { var evaluateInWindow = undefined, dataForWindow = {}, browserWindowOpts = undefined, converterPath = undefined, converter = undefined, currentWindow = undefined, currentWindowId = undefined, extraHeaders = ''; function respond(err, data) { log('finishing work in browser-window..'); if (err) { return respondIpc(err); } if (settingsData.collectLogs) { // eslint-disable-next-line no-param-reassign data.logs = global.windowsLogs[currentWindowId]; } else { // eslint-disable-next-line no-param-reassign data.logs = []; } respondIpc(null, data); if (!currentWindow) { return; } // in debug mode, don't destroy the browser window if (!DEBUG_MODE) { log('destroying browser window..'); currentWindow.destroy(); } } converterPath = settingsData.converterPath; log('requiring converter module from ' + converterPath); try { // eslint-disable-next-line global-require converter = require(converterPath); } catch (requireErr) { return respond(requireErr); } if (settingsData.waitForJS) { log('waitForJS enabled..'); dataForWindow.waitForJS = settingsData.waitForJS; dataForWindow.waitForJSVarName = settingsData.waitForJSVarName; } // get browser window options with defaults browserWindowOpts = getBrowserWindowOpts(settingsData.browserWindow); log('creating new browser window with options:', browserWindowOpts); if (DEBUG_MODE) { browserWindowOpts.show = true; } if (browserWindowOpts.show) { log('browser window visibility activated'); } currentWindow = new BrowserWindow(browserWindowOpts); currentWindowId = currentWindow.id; addWindow(currentWindow); evaluateInWindow = evaluate(currentWindow); global.windowsData[currentWindowId] = dataForWindow; global.windowsLogs[currentWindowId] = []; saveLogsInStore(global.windowsLogs[currentWindowId], 'debug', 'Converting using electron-ipc strategy in electron ' + electronVersion); currentWindow.webContents.setAudioMuted(true); listenRequestsInPage(currentWindow, { allowLocalFilesAccess: ALLOW_LOCAL_FILES_ACCESS, pageUrl: settingsData.url }, log, saveLogsInStore(global.windowsLogs[currentWindowId])); currentWindow.on('closed', function () { log('browser-window closed..'); delete global.windowsData[currentWindowId]; delete global.windowsLogs[currentWindowId]; removeWindow(currentWindow); currentWindow = null; }); conversionScript(settingsData, currentWindow, evaluateInWindow, log, converter, respond); if (settingsData.userAgent) { log('setting up custom user agent: ' + settingsData.userAgent); currentWindow.webContents.setUserAgent(settingsData.userAgent); } if (typeof settingsData.extraHeaders === 'object') { Object.keys(settingsData.extraHeaders).forEach(function (key) { extraHeaders += key + ': ' + settingsData.extraHeaders[key] + '\n'; }); } log(util.format('loading url in browser window: %s, with headers: %s', settingsData.url, extraHeaders)); if (extraHeaders) { currentWindow.loadURL(settingsData.url, { extraHeaders: extraHeaders }); } else { currentWindow.loadURL(settingsData.url); } // useful in windows to prevent the electron process to hang.. currentWindow.focus(); } function addWindow(browserWindow) { windows.push(browserWindow); } function removeWindow(browserWindow) { windows.forEach(function (win, index) { if (win === browserWindow) { windows.splice(index, 1); } }); } function saveLogsInStore(store, level, msg) { var userLevel = arguments.length <= 3 || arguments[3] === undefined ? false : arguments[3]; // eslint-disable-next-line prefer-rest-params var args = sliced(arguments); if (args.length === 1) { return _saveLogs.bind(undefined, store); } return _saveLogs(store, level, msg, userLevel); function _saveLogs(_store, _level, _msg, _userLevel) { var meta = { level: _level, message: trimMessage(_msg), timestamp: new Date().getTime() }; if (_userLevel) { meta.userLevel = true; } _store.push(meta); } } function trimMessage(args) { var message = args; if (Array.isArray(args)) { message = args.join(' '); } if (message.length > MAX_LOG_ENTRY_SIZE) { return message.substring(0, MAX_LOG_ENTRY_SIZE) + '...'; } return message; }