diff --git a/index.js b/index.js index 704ebc8..71afe9a 100644 --- a/index.js +++ b/index.js @@ -1,8 +1,19 @@ 'use strict'; const path = require('path'); const childProcess = require('child_process'); +const util = require('util'); const isWsl = require('is-wsl'); +const pExecFile = util.promisify(childProcess.execFile); + +// Converts a path from WSL format to Windows format +// e.g. /mnt/c/Program Files/Example/MyApp.exe +// => C:\Program Files\Example\MyApp.exe +const wslToWindowsPath = async path => { + const {stdout} = await pExecFile('wslpath', ['-w', path]); + return stdout.trim(); +}; + module.exports = async (target, options) => { if (typeof target !== 'string') { throw new TypeError('Expected a `target`'); @@ -43,6 +54,11 @@ module.exports = async (target, options) => { } if (options.app) { + if (isWsl && options.app.startsWith('/mnt/')) { + const winPath = await wslToWindowsPath(options.app); + options.app = winPath; + } + cliArguments.push(options.app); } diff --git a/readme.md b/readme.md index c534275..a852ca5 100644 --- a/readme.md +++ b/readme.md @@ -12,6 +12,7 @@ If need this for Electron, use [`shell.openItem()`](https://electronjs.org/docs/ - Safer as it uses `spawn` instead of `exec`. - Fixes most of the open `node-open` issues. - Includes the latest [`xdg-open` script](http://cgit.freedesktop.org/xdg/xdg-utils/commit/?id=c55122295c2a480fa721a9614f0e2d42b2949c18) for Linux. +- Supports WSL paths to Windows apps under `/mnt/*`. ## Install @@ -81,6 +82,8 @@ Specify the app to open the `target` with, or an array with the app and app argu The app name is platform dependent. Don't hard code it in reusable modules. For example, Chrome is `google chrome` on macOS, `google-chrome` on Linux and `chrome` on Windows. +You may also pass in the app's full path. For example on WSL, this can be `/mnt/c/Program Files (x86)/Google/Chrome/Application/chrome.exe` for the Windows installation of Chrome. + ## Related diff --git a/test.js b/test.js index 477e0c9..3d562d4 100644 --- a/test.js +++ b/test.js @@ -4,6 +4,8 @@ import open from '.'; let chromeName; let firefoxName; +let chromeWslName; +let firefoxWslName; if (process.platform === 'darwin') { chromeName = 'google chrome canary'; @@ -11,6 +13,8 @@ if (process.platform === 'darwin') { } else if (process.platform === 'win32' || isWsl) { chromeName = 'Chrome'; firefoxName = 'C:\\Program Files\\Mozilla Firefox\\firefox.exe'; + chromeWslName = '/mnt/c/Program Files (x86)/Google/Chrome/Application/chrome.exe'; + firefoxWslName = '/mnt/c/Program Files/Mozilla Firefox/firefox.exe'; } else if (process.platform === 'linux') { chromeName = 'google-chrome'; firefoxName = 'firefox'; @@ -45,3 +49,13 @@ test('return the child process when called', async t => { const cp = await open('index.js'); t.true('stdout' in cp); }); + +if (isWsl) { + test('open url in specified windows app given a wsl path to the app', async () => { + await open('http://sindresorhus.com', {app: firefoxWslName}); + }); + + test('open url in specified windows app with arguments given a wsl path to the app', async () => { + await open('http://sindresorhus.com', {app: [chromeWslName, '--incognito']}); + }); +}