'use strict' const path = require('path') const fs = require('fs') // Command-line parsing shared by boot and the single-instance handoff. // Supported: --launch , --file , --open , or a bare file path. // Electron re-serializes handoff argv, so options/positionals match in order. const VALUE_OPTIONS = ['--launch', '--file', '--open'] // Value options, the positionals that follow the switches, and inline // `--name=value` pairs. Tokens before the first switch are the executable // (matched against the running app path in dev mode and skipped). function splitArgv(argv) { const options = [] const positional = [] const inline = new Map() const appPath = process.defaultApp && process.argv[1] ? path.resolve(process.argv[1]) : null let switched = false for (const arg of Array.isArray(argv) ? argv : []) { if (typeof arg !== 'string' || !arg) continue if (arg.startsWith('-')) { switched = true const eq = arg.indexOf('=') const name = eq === -1 ? arg : arg.slice(0, eq) if (!VALUE_OPTIONS.includes(name)) continue if (eq === -1) options.push(name) else inline.set(name, arg.slice(eq + 1)) continue } // absolute in the handed-over argv, possibly relative here if (appPath && path.resolve(arg) === appPath) continue if (switched) positional.push(arg) } return { options, positional, inline } } // An option's value: inline `--name=value`, or the positional at the same // in-order position among the value options. function optionValue(parsed, name) { if (parsed.inline.has(name)) return parsed.inline.get(name) const index = parsed.options.indexOf(name) if (index === -1) return null const value = parsed.positional[index] return value === undefined ? null : value } // The file an app shortcut was asked to open; only an absolute path counts. const FIELD_CODE_RE = /^%[fFuUdDnNickvm]?$/ function launchFileOf(parsed, launchId) { const explicit = optionValue(parsed, '--file') // a literal %f token is never a file path if (explicit && !FIELD_CODE_RE.test(explicit) && path.isAbsolute(explicit)) return explicit if (!launchId) return null for (let i = parsed.positional.length - 1; i >= 0; i--) { const arg = parsed.positional[i] if (!path.isAbsolute(arg)) continue try { if (fs.statSync(arg).isFile()) return arg } catch {} } return null } function parseArgv(argv) { const args = Array.isArray(argv) ? argv : process.argv const parsed = splitArgv(args) const launchId = optionValue(parsed, '--launch') const launchFile = launchFileOf(parsed, launchId) let openPath = optionValue(parsed, '--open') if (!openPath && !launchId) { // Exec %f: the file path arrives as the only non-flag argument const bare = args.find( a => !a.startsWith('-') && /\.(exe|msi|bat|cmd|lnk)$/i.test(a) && !/\b(electron|olcxja\.plwl)(\.exe)?$/i.test(a) ) if (bare) openPath = bare } return { launchId, openPath, launchFile } } module.exports = { parseArgv }