@epic-web/workshop-utils 6.38.0 → 6.39.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
export type Result = {
|
|
2
|
+
status: 'success';
|
|
3
|
+
} | {
|
|
4
|
+
status: 'error';
|
|
5
|
+
message: string;
|
|
6
|
+
};
|
|
7
|
+
export declare function launchEditor(pathList: string[] | string, lineNumber?: number, colNumber?: number): Promise<Result>;
|
|
8
|
+
//# sourceMappingURL=launch-editor.server.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"launch-editor.server.d.ts","sourceRoot":"","sources":["../../src/launch-editor.server.ts"],"names":[],"mappings":"AAwRA,MAAM,MAAM,MAAM,GACf;IAAE,MAAM,EAAE,SAAS,CAAA;CAAE,GACrB;IAAE,MAAM,EAAE,OAAO,CAAC;IAAC,OAAO,EAAE,MAAM,CAAA;CAAE,CAAA;AACvC,wBAAsB,YAAY,CACjC,QAAQ,EAAE,MAAM,EAAE,GAAG,MAAM,EAC3B,UAAU,GAAE,MAAU,EACtB,SAAS,GAAE,MAAU,GACnB,OAAO,CAAC,MAAM,CAAC,CAiLjB"}
|
|
@@ -0,0 +1,379 @@
|
|
|
1
|
+
// copied (and barely modified) from create-react-app:
|
|
2
|
+
// https://github.com/facebook/create-react-app/blob/d960b9e38c062584ff6cfb1a70e1512509a966e7/packages/react-dev-utils/launchEditor.js
|
|
3
|
+
import child_process from 'child_process';
|
|
4
|
+
import fs from 'fs';
|
|
5
|
+
import os from 'os';
|
|
6
|
+
import path from 'path';
|
|
7
|
+
import fsExtra from 'fs-extra';
|
|
8
|
+
import shellQuote from 'shell-quote';
|
|
9
|
+
import { getRelativePath } from './apps.server.js';
|
|
10
|
+
function readablePath(filePath = '') {
|
|
11
|
+
const relative = getRelativePath(filePath);
|
|
12
|
+
const name = path.basename(relative);
|
|
13
|
+
const dir = path.dirname(relative);
|
|
14
|
+
return `'${name}' from:\n'${dir}'`;
|
|
15
|
+
}
|
|
16
|
+
function isTerminalEditor(editor) {
|
|
17
|
+
switch (editor) {
|
|
18
|
+
case 'vim':
|
|
19
|
+
case 'emacs':
|
|
20
|
+
case 'nano':
|
|
21
|
+
return true;
|
|
22
|
+
}
|
|
23
|
+
return false;
|
|
24
|
+
}
|
|
25
|
+
// Map from full process name to binary that starts the process
|
|
26
|
+
// We can't just re-use full process name, because it will spawn a new instance
|
|
27
|
+
// of the app every time
|
|
28
|
+
const COMMON_EDITORS_OSX = {
|
|
29
|
+
'/Applications/Atom.app/Contents/MacOS/Atom': 'atom',
|
|
30
|
+
'/Applications/Atom Beta.app/Contents/MacOS/Atom Beta': '/Applications/Atom Beta.app/Contents/MacOS/Atom Beta',
|
|
31
|
+
'/Applications/Brackets.app/Contents/MacOS/Brackets': 'brackets',
|
|
32
|
+
'/Applications/Sublime Text.app/Contents/MacOS/Sublime Text': '/Applications/Sublime Text.app/Contents/SharedSupport/bin/subl',
|
|
33
|
+
'/Applications/Sublime Text Dev.app/Contents/MacOS/Sublime Text': '/Applications/Sublime Text Dev.app/Contents/SharedSupport/bin/subl',
|
|
34
|
+
'/Applications/Sublime Text 2.app/Contents/MacOS/Sublime Text 2': '/Applications/Sublime Text 2.app/Contents/SharedSupport/bin/subl',
|
|
35
|
+
'/Applications/Cursor.app/Contents/MacOS/Cursor': 'cursor',
|
|
36
|
+
'/Applications/Visual Studio Code.app/Contents/MacOS/Electron': 'code',
|
|
37
|
+
'/Applications/Visual Studio Code - Insiders.app/Contents/MacOS/Electron': 'code-insiders',
|
|
38
|
+
'/Applications/VSCodium.app/Contents/MacOS/Electron': 'vscodium',
|
|
39
|
+
'/Applications/AppCode.app/Contents/MacOS/appcode': '/Applications/AppCode.app/Contents/MacOS/appcode',
|
|
40
|
+
'/Applications/CLion.app/Contents/MacOS/clion': '/Applications/CLion.app/Contents/MacOS/clion',
|
|
41
|
+
'/Applications/IntelliJ IDEA.app/Contents/MacOS/idea': '/Applications/IntelliJ IDEA.app/Contents/MacOS/idea',
|
|
42
|
+
'/Applications/PhpStorm.app/Contents/MacOS/phpstorm': '/Applications/PhpStorm.app/Contents/MacOS/phpstorm',
|
|
43
|
+
'/Applications/PyCharm.app/Contents/MacOS/pycharm': '/Applications/PyCharm.app/Contents/MacOS/pycharm',
|
|
44
|
+
'/Applications/PyCharm CE.app/Contents/MacOS/pycharm': '/Applications/PyCharm CE.app/Contents/MacOS/pycharm',
|
|
45
|
+
'/Applications/RubyMine.app/Contents/MacOS/rubymine': '/Applications/RubyMine.app/Contents/MacOS/rubymine',
|
|
46
|
+
'/Applications/WebStorm.app/Contents/MacOS/webstorm': '/Applications/WebStorm.app/Contents/MacOS/webstorm',
|
|
47
|
+
'/Applications/MacVim.app/Contents/MacOS/MacVim': 'mvim',
|
|
48
|
+
'/Applications/GoLand.app/Contents/MacOS/goland': '/Applications/GoLand.app/Contents/MacOS/goland',
|
|
49
|
+
'/Applications/Rider.app/Contents/MacOS/rider': '/Applications/Rider.app/Contents/MacOS/rider',
|
|
50
|
+
'/Applications/Zed/Zed.app/Contents/MacOS/zed': 'zed',
|
|
51
|
+
};
|
|
52
|
+
const COMMON_EDITORS_LINUX = {
|
|
53
|
+
atom: 'atom',
|
|
54
|
+
Brackets: 'brackets',
|
|
55
|
+
cursor: 'cursor',
|
|
56
|
+
code: 'code',
|
|
57
|
+
'code-insiders': 'code-insiders',
|
|
58
|
+
vscodium: 'vscodium',
|
|
59
|
+
emacs: 'emacs',
|
|
60
|
+
gvim: 'gvim',
|
|
61
|
+
'idea.sh': 'idea',
|
|
62
|
+
'phpstorm.sh': 'phpstorm',
|
|
63
|
+
'pycharm.sh': 'pycharm',
|
|
64
|
+
'rubymine.sh': 'rubymine',
|
|
65
|
+
sublime_text: 'sublime_text',
|
|
66
|
+
vim: 'vim',
|
|
67
|
+
'webstorm.sh': 'webstorm',
|
|
68
|
+
'goland.sh': 'goland',
|
|
69
|
+
'rider.sh': 'rider',
|
|
70
|
+
zed: 'zed',
|
|
71
|
+
};
|
|
72
|
+
const COMMON_EDITORS_WIN = [
|
|
73
|
+
'Brackets.exe',
|
|
74
|
+
'Cursor.exe',
|
|
75
|
+
'Code.exe',
|
|
76
|
+
'Code - Insiders.exe',
|
|
77
|
+
'VSCodium.exe',
|
|
78
|
+
'atom.exe',
|
|
79
|
+
'sublime_text.exe',
|
|
80
|
+
'notepad++.exe',
|
|
81
|
+
'clion.exe',
|
|
82
|
+
'clion64.exe',
|
|
83
|
+
'idea.exe',
|
|
84
|
+
'idea64.exe',
|
|
85
|
+
'phpstorm.exe',
|
|
86
|
+
'phpstorm64.exe',
|
|
87
|
+
'pycharm.exe',
|
|
88
|
+
'pycharm64.exe',
|
|
89
|
+
'rubymine.exe',
|
|
90
|
+
'rubymine64.exe',
|
|
91
|
+
'webstorm.exe',
|
|
92
|
+
'webstorm64.exe',
|
|
93
|
+
'goland.exe',
|
|
94
|
+
'goland64.exe',
|
|
95
|
+
'rider.exe',
|
|
96
|
+
'rider64.exe',
|
|
97
|
+
'zed.exe',
|
|
98
|
+
];
|
|
99
|
+
// Transpiled version of: /^([A-Za-z]:[/\\])?[\p{L}0-9/.\-_\\]+$/u
|
|
100
|
+
// Non-transpiled version requires support for Unicode property regex. Allows
|
|
101
|
+
// alphanumeric characters, periods, dashes, slashes, and underscores.
|
|
102
|
+
const WINDOWS_FILE_NAME_WHITELIST = /^([A-Za-z]:[/\\])?(?:[\x2D-9A-Z\\_a-z\xAA\xB5\xBA\xC0-\xD6\xD8-\xF6\xF8-\u02C1\u02C6-\u02D1\u02E0-\u02E4\u02EC\u02EE\u0370-\u0374\u0376\u0377\u037A-\u037D\u037F\u0386\u0388-\u038A\u038C\u038E-\u03A1\u03A3-\u03F5\u03F7-\u0481\u048A-\u052F\u0531-\u0556\u0559\u0560-\u0588\u05D0-\u05EA\u05EF-\u05F2\u0620-\u064A\u066E\u066F\u0671-\u06D3\u06D5\u06E5\u06E6\u06EE\u06EF\u06FA-\u06FC\u06FF\u0710\u0712-\u072F\u074D-\u07A5\u07B1\u07CA-\u07EA\u07F4\u07F5\u07FA\u0800-\u0815\u081A\u0824\u0828\u0840-\u0858\u0860-\u086A\u08A0-\u08B4\u08B6-\u08BD\u0904-\u0939\u093D\u0950\u0958-\u0961\u0971-\u0980\u0985-\u098C\u098F\u0990\u0993-\u09A8\u09AA-\u09B0\u09B2\u09B6-\u09B9\u09BD\u09CE\u09DC\u09DD\u09DF-\u09E1\u09F0\u09F1\u09FC\u0A05-\u0A0A\u0A0F\u0A10\u0A13-\u0A28\u0A2A-\u0A30\u0A32\u0A33\u0A35\u0A36\u0A38\u0A39\u0A59-\u0A5C\u0A5E\u0A72-\u0A74\u0A85-\u0A8D\u0A8F-\u0A91\u0A93-\u0AA8\u0AAA-\u0AB0\u0AB2\u0AB3\u0AB5-\u0AB9\u0ABD\u0AD0\u0AE0\u0AE1\u0AF9\u0B05-\u0B0C\u0B0F\u0B10\u0B13-\u0B28\u0B2A-\u0B30\u0B32\u0B33\u0B35-\u0B39\u0B3D\u0B5C\u0B5D\u0B5F-\u0B61\u0B71\u0B83\u0B85-\u0B8A\u0B8E-\u0B90\u0B92-\u0B95\u0B99\u0B9A\u0B9C\u0B9E\u0B9F\u0BA3\u0BA4\u0BA8-\u0BAA\u0BAE-\u0BB9\u0BD0\u0C05-\u0C0C\u0C0E-\u0C10\u0C12-\u0C28\u0C2A-\u0C39\u0C3D\u0C58-\u0C5A\u0C60\u0C61\u0C80\u0C85-\u0C8C\u0C8E-\u0C90\u0C92-\u0CA8\u0CAA-\u0CB3\u0CB5-\u0CB9\u0CBD\u0CDE\u0CE0\u0CE1\u0CF1\u0CF2\u0D05-\u0D0C\u0D0E-\u0D10\u0D12-\u0D3A\u0D3D\u0D4E\u0D54-\u0D56\u0D5F-\u0D61\u0D7A-\u0D7F\u0D85-\u0D96\u0D9A-\u0DB1\u0DB3-\u0DBB\u0DBD\u0DC0-\u0DC6\u0E01-\u0E30\u0E32\u0E33\u0E40-\u0E46\u0E81\u0E82\u0E84\u0E87\u0E88\u0E8A\u0E8D\u0E94-\u0E97\u0E99-\u0E9F\u0EA1-\u0EA3\u0EA5\u0EA7\u0EAA\u0EAB\u0EAD-\u0EB0\u0EB2\u0EB3\u0EBD\u0EC0-\u0EC4\u0EC6\u0EDC-\u0EDF\u0F00\u0F40-\u0F47\u0F49-\u0F6C\u0F88-\u0F8C\u1000-\u102A\u103F\u1050-\u1055\u105A-\u105D\u1061\u1065\u1066\u106E-\u1070\u1075-\u1081\u108E\u10A0-\u10C5\u10C7\u10CD\u10D0-\u10FA\u10FC-\u1248\u124A-\u124D\u1250-\u1256\u1258\u125A-\u125D\u1260-\u1288\u128A-\u128D\u1290-\u12B0\u12B2-\u12B5\u12B8-\u12BE\u12C0\u12C2-\u12C5\u12C8-\u12D6\u12D8-\u1310\u1312-\u1315\u1318-\u135A\u1380-\u138F\u13A0-\u13F5\u13F8-\u13FD\u1401-\u166C\u166F-\u167F\u1681-\u169A\u16A0-\u16EA\u16F1-\u16F8\u1700-\u170C\u170E-\u1711\u1720-\u1731\u1740-\u1751\u1760-\u176C\u176E-\u1770\u1780-\u17B3\u17D7\u17DC\u1820-\u1878\u1880-\u1884\u1887-\u18A8\u18AA\u18B0-\u18F5\u1900-\u191E\u1950-\u196D\u1970-\u1974\u1980-\u19AB\u19B0-\u19C9\u1A00-\u1A16\u1A20-\u1A54\u1AA7\u1B05-\u1B33\u1B45-\u1B4B\u1B83-\u1BA0\u1BAE\u1BAF\u1BBA-\u1BE5\u1C00-\u1C23\u1C4D-\u1C4F\u1C5A-\u1C7D\u1C80-\u1C88\u1C90-\u1CBA\u1CBD-\u1CBF\u1CE9-\u1CEC\u1CEE-\u1CF1\u1CF5\u1CF6\u1D00-\u1DBF\u1E00-\u1F15\u1F18-\u1F1D\u1F20-\u1F45\u1F48-\u1F4D\u1F50-\u1F57\u1F59\u1F5B\u1F5D\u1F5F-\u1F7D\u1F80-\u1FB4\u1FB6-\u1FBC\u1FBE\u1FC2-\u1FC4\u1FC6-\u1FCC\u1FD0-\u1FD3\u1FD6-\u1FDB\u1FE0-\u1FEC\u1FF2-\u1FF4\u1FF6-\u1FFC\u2071\u207F\u2090-\u209C\u2102\u2107\u210A-\u2113\u2115\u2119-\u211D\u2124\u2126\u2128\u212A-\u212D\u212F-\u2139\u213C-\u213F\u2145-\u2149\u214E\u2183\u2184\u2C00-\u2C2E\u2C30-\u2C5E\u2C60-\u2CE4\u2CEB-\u2CEE\u2CF2\u2CF3\u2D00-\u2D25\u2D27\u2D2D\u2D30-\u2D67\u2D6F\u2D80-\u2D96\u2DA0-\u2DA6\u2DA8-\u2DAE\u2DB0-\u2DB6\u2DB8-\u2DBE\u2DC0-\u2DC6\u2DC8-\u2DCE\u2DD0-\u2DD6\u2DD8-\u2DDE\u2E2F\u3005\u3006\u3031-\u3035\u303B\u303C\u3041-\u3096\u309D-\u309F\u30A1-\u30FA\u30FC-\u30FF\u3105-\u312F\u3131-\u318E\u31A0-\u31BA\u31F0-\u31FF\u3400-\u4DB5\u4E00-\u9FEF\uA000-\uA48C\uA4D0-\uA4FD\uA500-\uA60C\uA610-\uA61F\uA62A\uA62B\uA640-\uA66E\uA67F-\uA69D\uA6A0-\uA6E5\uA717-\uA71F\uA722-\uA788\uA78B-\uA7B9\uA7F7-\uA801\uA803-\uA805\uA807-\uA80A\uA80C-\uA822\uA840-\uA873\uA882-\uA8B3\uA8F2-\uA8F7\uA8FB\uA8FD\uA8FE\uA90A-\uA925\uA930-\uA946\uA960-\uA97C\uA984-\uA9B2\uA9CF\uA9E0-\uA9E4\uA9E6-\uA9EF\uA9FA-\uA9FE\uAA00-\uAA28\uAA40-\uAA42\uAA44-\uAA4B\uAA60-\uAA76\uAA7A\uAA7E-\uAAAF\uAAB1\uAAB5\uAAB6\uAAB9-\uAABD\uAAC0\uAAC2\uAADB-\uAADD\uAAE0-\uAAEA\uAAF2-\uAAF4\uAB01-\uAB06\uAB09-\uAB0E\uAB11-\uAB16\uAB20-\uAB26\uAB28-\uAB2E\uAB30-\uAB5A\uAB5C-\uAB65\uAB70-\uABE2\uAC00-\uD7A3\uD7B0-\uD7C6\uD7CB-\uD7FB\uF900-\uFA6D\uFA70-\uFAD9\uFB00-\uFB06\uFB13-\uFB17\uFB1D\uFB1F-\uFB28\uFB2A-\uFB36\uFB38-\uFB3C\uFB3E\uFB40\uFB41\uFB43\uFB44\uFB46-\uFBB1\uFBD3-\uFD3D\uFD50-\uFD8F\uFD92-\uFDC7\uFDF0-\uFDFB\uFE70-\uFE74\uFE76-\uFEFC\uFF21-\uFF3A\uFF41-\uFF5A\uFF66-\uFFBE\uFFC2-\uFFC7\uFFCA-\uFFCF\uFFD2-\uFFD7\uFFDA-\uFFDC]|\uD800[\uDC00-\uDC0B\uDC0D-\uDC26\uDC28-\uDC3A\uDC3C\uDC3D\uDC3F-\uDC4D\uDC50-\uDC5D\uDC80-\uDCFA\uDE80-\uDE9C\uDEA0-\uDED0\uDF00-\uDF1F\uDF2D-\uDF40\uDF42-\uDF49\uDF50-\uDF75\uDF80-\uDF9D\uDFA0-\uDFC3\uDFC8-\uDFCF]|\uD801[\uDC00-\uDC9D\uDCB0-\uDCD3\uDCD8-\uDCFB\uDD00-\uDD27\uDD30-\uDD63\uDE00-\uDF36\uDF40-\uDF55\uDF60-\uDF67]|\uD802[\uDC00-\uDC05\uDC08\uDC0A-\uDC35\uDC37\uDC38\uDC3C\uDC3F-\uDC55\uDC60-\uDC76\uDC80-\uDC9E\uDCE0-\uDCF2\uDCF4\uDCF5\uDD00-\uDD15\uDD20-\uDD39\uDD80-\uDDB7\uDDBE\uDDBF\uDE00\uDE10-\uDE13\uDE15-\uDE17\uDE19-\uDE35\uDE60-\uDE7C\uDE80-\uDE9C\uDEC0-\uDEC7\uDEC9-\uDEE4\uDF00-\uDF35\uDF40-\uDF55\uDF60-\uDF72\uDF80-\uDF91]|\uD803[\uDC00-\uDC48\uDC80-\uDCB2\uDCC0-\uDCF2\uDD00-\uDD23\uDF00-\uDF1C\uDF27\uDF30-\uDF45]|\uD804[\uDC03-\uDC37\uDC83-\uDCAF\uDCD0-\uDCE8\uDD03-\uDD26\uDD44\uDD50-\uDD72\uDD76\uDD83-\uDDB2\uDDC1-\uDDC4\uDDDA\uDDDC\uDE00-\uDE11\uDE13-\uDE2B\uDE80-\uDE86\uDE88\uDE8A-\uDE8D\uDE8F-\uDE9D\uDE9F-\uDEA8\uDEB0-\uDEDE\uDF05-\uDF0C\uDF0F\uDF10\uDF13-\uDF28\uDF2A-\uDF30\uDF32\uDF33\uDF35-\uDF39\uDF3D\uDF50\uDF5D-\uDF61]|\uD805[\uDC00-\uDC34\uDC47-\uDC4A\uDC80-\uDCAF\uDCC4\uDCC5\uDCC7\uDD80-\uDDAE\uDDD8-\uDDDB\uDE00-\uDE2F\uDE44\uDE80-\uDEAA\uDF00-\uDF1A]|\uD806[\uDC00-\uDC2B\uDCA0-\uDCDF\uDCFF\uDE00\uDE0B-\uDE32\uDE3A\uDE50\uDE5C-\uDE83\uDE86-\uDE89\uDE9D\uDEC0-\uDEF8]|\uD807[\uDC00-\uDC08\uDC0A-\uDC2E\uDC40\uDC72-\uDC8F\uDD00-\uDD06\uDD08\uDD09\uDD0B-\uDD30\uDD46\uDD60-\uDD65\uDD67\uDD68\uDD6A-\uDD89\uDD98\uDEE0-\uDEF2]|\uD808[\uDC00-\uDF99]|\uD809[\uDC80-\uDD43]|[\uD80C\uD81C-\uD820\uD840-\uD868\uD86A-\uD86C\uD86F-\uD872\uD874-\uD879][\uDC00-\uDFFF]|\uD80D[\uDC00-\uDC2E]|\uD811[\uDC00-\uDE46]|\uD81A[\uDC00-\uDE38\uDE40-\uDE5E\uDED0-\uDEED\uDF00-\uDF2F\uDF40-\uDF43\uDF63-\uDF77\uDF7D-\uDF8F]|\uD81B[\uDE40-\uDE7F\uDF00-\uDF44\uDF50\uDF93-\uDF9F\uDFE0\uDFE1]|\uD821[\uDC00-\uDFF1]|\uD822[\uDC00-\uDEF2]|\uD82C[\uDC00-\uDD1E\uDD70-\uDEFB]|\uD82F[\uDC00-\uDC6A\uDC70-\uDC7C\uDC80-\uDC88\uDC90-\uDC99]|\uD835[\uDC00-\uDC54\uDC56-\uDC9C\uDC9E\uDC9F\uDCA2\uDCA5\uDCA6\uDCA9-\uDCAC\uDCAE-\uDCB9\uDCBB\uDCBD-\uDCC3\uDCC5-\uDD05\uDD07-\uDD0A\uDD0D-\uDD14\uDD16-\uDD1C\uDD1E-\uDD39\uDD3B-\uDD3E\uDD40-\uDD44\uDD46\uDD4A-\uDD50\uDD52-\uDEA5\uDEA8-\uDEC0\uDEC2-\uDEDA\uDEDC-\uDEFA\uDEFC-\uDF14\uDF16-\uDF34\uDF36-\uDF4E\uDF50-\uDF6E\uDF70-\uDF88\uDF8A-\uDFA8\uDFAA-\uDFC2\uDFC4-\uDFCB]|\uD83A[\uDC00-\uDCC4\uDD00-\uDD43]|\uD83B[\uDE00-\uDE03\uDE05-\uDE1F\uDE21\uDE22\uDE24\uDE27\uDE29-\uDE32\uDE34-\uDE37\uDE39\uDE3B\uDE42\uDE47\uDE49\uDE4B\uDE4D-\uDE4F\uDE51\uDE52\uDE54\uDE57\uDE59\uDE5B\uDE5D\uDE5F\uDE61\uDE62\uDE64\uDE67-\uDE6A\uDE6C-\uDE72\uDE74-\uDE77\uDE79-\uDE7C\uDE7E\uDE80-\uDE89\uDE8B-\uDE9B\uDEA1-\uDEA3\uDEA5-\uDEA9\uDEAB-\uDEBB]|\uD869[\uDC00-\uDED6\uDF00-\uDFFF]|\uD86D[\uDC00-\uDF34\uDF40-\uDFFF]|\uD86E[\uDC00-\uDC1D\uDC20-\uDFFF]|\uD873[\uDC00-\uDEA1\uDEB0-\uDFFF]|\uD87A[\uDC00-\uDFE0]|\uD87E[\uDC00-\uDE1D])+$/;
|
|
103
|
+
function addWorkspaceToArgumentsIfExists(args, workspace) {
|
|
104
|
+
if (workspace) {
|
|
105
|
+
args.unshift(workspace);
|
|
106
|
+
}
|
|
107
|
+
return args;
|
|
108
|
+
}
|
|
109
|
+
function getArgumentsForLineNumber(editor, fileName, lineNumber, colNumber, workspace) {
|
|
110
|
+
const editorBasename = path.basename(editor).replace(/\.(exe|cmd|bat)$/i, '');
|
|
111
|
+
switch (editorBasename) {
|
|
112
|
+
case 'atom':
|
|
113
|
+
case 'Atom':
|
|
114
|
+
case 'Atom Beta':
|
|
115
|
+
case 'subl':
|
|
116
|
+
case 'sublime':
|
|
117
|
+
case 'sublime_text':
|
|
118
|
+
return [`${fileName}:${lineNumber}:${colNumber}`];
|
|
119
|
+
case 'wstorm':
|
|
120
|
+
case 'charm':
|
|
121
|
+
return [`${fileName}:${lineNumber}`];
|
|
122
|
+
case 'notepad++':
|
|
123
|
+
return [`-n${lineNumber}`, `-c${colNumber}`, fileName];
|
|
124
|
+
case 'vim':
|
|
125
|
+
case 'mvim':
|
|
126
|
+
case 'joe':
|
|
127
|
+
case 'gvim':
|
|
128
|
+
return [`+${lineNumber}`, fileName];
|
|
129
|
+
case 'emacs':
|
|
130
|
+
case 'emacsclient':
|
|
131
|
+
return [`+${lineNumber}:${colNumber}`, fileName];
|
|
132
|
+
case 'rmate':
|
|
133
|
+
case 'mate':
|
|
134
|
+
case 'mine':
|
|
135
|
+
return ['--line', lineNumber, fileName];
|
|
136
|
+
case 'cursor':
|
|
137
|
+
case 'code':
|
|
138
|
+
case 'Code':
|
|
139
|
+
case 'code-insiders':
|
|
140
|
+
case 'Code - Insiders':
|
|
141
|
+
case 'vscodium':
|
|
142
|
+
case 'VSCodium':
|
|
143
|
+
return addWorkspaceToArgumentsIfExists(['-g', `${fileName}:${lineNumber}:${colNumber}`], workspace);
|
|
144
|
+
case 'appcode':
|
|
145
|
+
case 'clion':
|
|
146
|
+
case 'clion64':
|
|
147
|
+
case 'idea':
|
|
148
|
+
case 'idea64':
|
|
149
|
+
case 'phpstorm':
|
|
150
|
+
case 'phpstorm64':
|
|
151
|
+
case 'pycharm':
|
|
152
|
+
case 'pycharm64':
|
|
153
|
+
case 'rubymine':
|
|
154
|
+
case 'rubymine64':
|
|
155
|
+
case 'webstorm':
|
|
156
|
+
case 'webstorm64':
|
|
157
|
+
case 'goland':
|
|
158
|
+
case 'goland64':
|
|
159
|
+
case 'rider':
|
|
160
|
+
case 'rider64':
|
|
161
|
+
return addWorkspaceToArgumentsIfExists(['--line', lineNumber.toString(), fileName], workspace);
|
|
162
|
+
}
|
|
163
|
+
// For all others, drop the lineNumber until we have
|
|
164
|
+
// a mapping above, since providing the lineNumber incorrectly
|
|
165
|
+
// can result in errors or confusing behavior.
|
|
166
|
+
return [fileName];
|
|
167
|
+
}
|
|
168
|
+
function guessEditor() {
|
|
169
|
+
// Explicit config always wins
|
|
170
|
+
if (process.env.EPICSHOP_EDITOR) {
|
|
171
|
+
return shellQuote.parse(process.env.EPICSHOP_EDITOR).map((a) => String(a));
|
|
172
|
+
}
|
|
173
|
+
// We can find out which editor is currently running by:
|
|
174
|
+
// `ps x` on macOS and Linux
|
|
175
|
+
// `Get-Process` on Windows
|
|
176
|
+
try {
|
|
177
|
+
if (process.platform === 'darwin') {
|
|
178
|
+
const output = child_process.execSync('ps x').toString();
|
|
179
|
+
const processNames = Object.keys(COMMON_EDITORS_OSX);
|
|
180
|
+
for (let i = 0; i < processNames.length; i++) {
|
|
181
|
+
const processName = processNames[i];
|
|
182
|
+
if (processName && output.includes(processName)) {
|
|
183
|
+
const editor = COMMON_EDITORS_OSX[processName];
|
|
184
|
+
return [editor];
|
|
185
|
+
}
|
|
186
|
+
}
|
|
187
|
+
}
|
|
188
|
+
else if (process.platform === 'win32') {
|
|
189
|
+
// Some processes need elevated rights to get its executable path.
|
|
190
|
+
// Just filter them out upfront. This also saves 10-20ms on the command.
|
|
191
|
+
const output = child_process
|
|
192
|
+
.execSync('wmic process where "executablepath is not null" get executablepath')
|
|
193
|
+
.toString();
|
|
194
|
+
const runningProcesses = output.split('\r\n');
|
|
195
|
+
for (let i = 0; i < runningProcesses.length; i++) {
|
|
196
|
+
const processPath = runningProcesses[i]?.trim();
|
|
197
|
+
if (!processPath)
|
|
198
|
+
continue;
|
|
199
|
+
const processName = path.basename(processPath);
|
|
200
|
+
if (COMMON_EDITORS_WIN.includes(processName)) {
|
|
201
|
+
return [processPath];
|
|
202
|
+
}
|
|
203
|
+
}
|
|
204
|
+
}
|
|
205
|
+
else if (process.platform === 'linux') {
|
|
206
|
+
// --no-heading No header line
|
|
207
|
+
// x List all processes owned by you
|
|
208
|
+
// -o comm Need only names column
|
|
209
|
+
const output = child_process
|
|
210
|
+
.execSync('ps x --no-heading -o comm --sort=comm')
|
|
211
|
+
.toString();
|
|
212
|
+
const processNames = Object.keys(COMMON_EDITORS_LINUX);
|
|
213
|
+
for (let i = 0; i < processNames.length; i++) {
|
|
214
|
+
const processName = processNames[i];
|
|
215
|
+
if (!processName)
|
|
216
|
+
continue;
|
|
217
|
+
if (output.includes(processName)) {
|
|
218
|
+
// @ts-expect-error 🤷♂️ it's fine
|
|
219
|
+
return [COMMON_EDITORS_LINUX[processName]];
|
|
220
|
+
}
|
|
221
|
+
}
|
|
222
|
+
}
|
|
223
|
+
}
|
|
224
|
+
catch {
|
|
225
|
+
// Ignore...
|
|
226
|
+
}
|
|
227
|
+
// Last resort, use old skool env vars
|
|
228
|
+
if (process.env.VISUAL) {
|
|
229
|
+
return [process.env.VISUAL];
|
|
230
|
+
}
|
|
231
|
+
else if (process.env.EDITOR) {
|
|
232
|
+
return [process.env.EDITOR];
|
|
233
|
+
}
|
|
234
|
+
return [null];
|
|
235
|
+
}
|
|
236
|
+
let _childProcess = null;
|
|
237
|
+
export async function launchEditor(pathList, lineNumber = 1, colNumber = 1) {
|
|
238
|
+
// Sanitize lineNumber to prevent malicious use on win32
|
|
239
|
+
// via: https://github.com/nodejs/node/blob/c3bb4b1aa5e907d489619fb43d233c3336bfc03d/lib/child_process.js#L333
|
|
240
|
+
// and it should be a positive integer
|
|
241
|
+
if (lineNumber && !(Number.isInteger(lineNumber) && lineNumber > 0)) {
|
|
242
|
+
return { status: 'error', message: 'lineNumber must be a positive integer' };
|
|
243
|
+
}
|
|
244
|
+
// colNumber is optional, but should be a positive integer too
|
|
245
|
+
// default is 1
|
|
246
|
+
if (colNumber && !(Number.isInteger(colNumber) && colNumber > 0)) {
|
|
247
|
+
colNumber = 1;
|
|
248
|
+
}
|
|
249
|
+
const editorInfo = guessEditor();
|
|
250
|
+
const editor = editorInfo[0];
|
|
251
|
+
let args = editorInfo.slice(1).filter(Boolean);
|
|
252
|
+
if (!editor) {
|
|
253
|
+
return { status: 'error', message: 'No editor found' };
|
|
254
|
+
}
|
|
255
|
+
if (editor.toLowerCase() === 'none') {
|
|
256
|
+
return { status: 'error', message: 'Editor set to "none"' };
|
|
257
|
+
}
|
|
258
|
+
if (typeof pathList === 'string') {
|
|
259
|
+
pathList = [pathList];
|
|
260
|
+
}
|
|
261
|
+
const initArgs = { fileList: [], errorsList: [] };
|
|
262
|
+
const { fileList, errorsList } = pathList.reduce((acc, fileName) => {
|
|
263
|
+
if (process.platform === 'linux' &&
|
|
264
|
+
fileName.startsWith('/mnt/') &&
|
|
265
|
+
/Microsoft/i.test(os.release())) {
|
|
266
|
+
// Assume WSL / "Bash on Ubuntu on Windows" is being used, and
|
|
267
|
+
// that the file exists on the Windows file system.
|
|
268
|
+
// `os.release()` is "4.4.0-43-Microsoft" in the current release
|
|
269
|
+
// build of WSL, see: https://github.com/Microsoft/BashOnWindows/issues/423#issuecomment-221627364
|
|
270
|
+
// When a Windows editor is specified, interop functionality can
|
|
271
|
+
// handle the path translation, but only if a relative path is used.
|
|
272
|
+
fileName = path.relative('', fileName);
|
|
273
|
+
}
|
|
274
|
+
const fileExists = fs.existsSync(fileName);
|
|
275
|
+
// cmd.exe on Windows is vulnerable to RCE attacks given a file name of the
|
|
276
|
+
// form "C:\Users\myusername\Downloads\& curl 172.21.93.52". Use a whitelist
|
|
277
|
+
// to validate user-provided file names. This doesn't cover the entire range
|
|
278
|
+
// of valid file names but should cover almost all of them in practice.
|
|
279
|
+
// if the file exists, then we're good.
|
|
280
|
+
if (!fileExists &&
|
|
281
|
+
process.platform === 'win32' &&
|
|
282
|
+
!WINDOWS_FILE_NAME_WHITELIST.test(fileName)) {
|
|
283
|
+
acc.errorsList.push(fileName);
|
|
284
|
+
}
|
|
285
|
+
else {
|
|
286
|
+
if (!fileExists) {
|
|
287
|
+
fsExtra.ensureDirSync(path.dirname(fileName));
|
|
288
|
+
fsExtra.writeFileSync(fileName, '', 'utf8');
|
|
289
|
+
}
|
|
290
|
+
acc.fileList.push(fileName.trim());
|
|
291
|
+
}
|
|
292
|
+
return acc;
|
|
293
|
+
}, initArgs);
|
|
294
|
+
// TODO: figure out how to send error messages as JSX from here...
|
|
295
|
+
function getErrorMessage() {
|
|
296
|
+
let message;
|
|
297
|
+
if (errorsList.length) {
|
|
298
|
+
const readableName = errorsList.length === 1 ? readablePath(errorsList[0]) : 'some files';
|
|
299
|
+
message = `Could not open ${readableName} in the editor.\n\nWhen running on Windows, file names are checked against a whitelist to protect against remote code execution attacks.\nFile names may consist only of alphanumeric characters (all languages), periods, dashes, slashes, and underscores. Maybe you have your files in a folder that includes a space in the pathname? Rename the folder to remove the space and try again.`;
|
|
300
|
+
}
|
|
301
|
+
else {
|
|
302
|
+
message = 'pathList must contain at least one valid file path';
|
|
303
|
+
}
|
|
304
|
+
return {
|
|
305
|
+
status: 'error',
|
|
306
|
+
message,
|
|
307
|
+
};
|
|
308
|
+
}
|
|
309
|
+
const workspace = null;
|
|
310
|
+
if (lineNumber && fileList.length === 1) {
|
|
311
|
+
const fileName = fileList[0];
|
|
312
|
+
if (!fileName) {
|
|
313
|
+
return getErrorMessage();
|
|
314
|
+
}
|
|
315
|
+
args = args.concat(getArgumentsForLineNumber(editor, fileName, lineNumber, colNumber, workspace)
|
|
316
|
+
.filter(Boolean)
|
|
317
|
+
.map(String));
|
|
318
|
+
}
|
|
319
|
+
else {
|
|
320
|
+
const argList = fileList.filter(Boolean);
|
|
321
|
+
if (!argList.length) {
|
|
322
|
+
return getErrorMessage();
|
|
323
|
+
}
|
|
324
|
+
args.push(...argList);
|
|
325
|
+
}
|
|
326
|
+
if (_childProcess && isTerminalEditor(editor)) {
|
|
327
|
+
// There's an existing editor process already and it's attached
|
|
328
|
+
// to the terminal, so go kill it. Otherwise two separate editor
|
|
329
|
+
// instances attach to the stdin/stdout which gets confusing.
|
|
330
|
+
_childProcess.kill('SIGKILL');
|
|
331
|
+
}
|
|
332
|
+
return new Promise((res) => {
|
|
333
|
+
if (process.platform === 'win32') {
|
|
334
|
+
// On Windows, launch the editor in a shell because spawn can only
|
|
335
|
+
// launch .exe files.
|
|
336
|
+
_childProcess = child_process.spawn('cmd.exe', ['/C', editor].concat(args).filter(Boolean), { stdio: ['inherit', 'inherit', 'pipe'] });
|
|
337
|
+
}
|
|
338
|
+
else {
|
|
339
|
+
_childProcess = child_process.spawn(editor, args, {
|
|
340
|
+
stdio: ['inherit', 'inherit', 'pipe'],
|
|
341
|
+
});
|
|
342
|
+
}
|
|
343
|
+
_childProcess.stderr?.on('data', (data) => {
|
|
344
|
+
const message = String(data);
|
|
345
|
+
// Filter out the specific error message for environment variable issues
|
|
346
|
+
if (!message.includes('Node.js environment variables are disabled')) {
|
|
347
|
+
process.stderr.write(data); // Only write non-filtered messages to stderr
|
|
348
|
+
}
|
|
349
|
+
});
|
|
350
|
+
_childProcess.on('exit', async (errorCode) => {
|
|
351
|
+
_childProcess = null;
|
|
352
|
+
if (errorCode) {
|
|
353
|
+
const readableName = fileList.length === 1 ? readablePath(fileList[0]) : 'some files';
|
|
354
|
+
return res({
|
|
355
|
+
status: 'error',
|
|
356
|
+
message: `Could not open ${readableName} in the editor.\n\nThe editor process exited with an error code (${errorCode}).`,
|
|
357
|
+
});
|
|
358
|
+
}
|
|
359
|
+
else if (errorsList.length) {
|
|
360
|
+
// show error message even when the editor was opened successfully,
|
|
361
|
+
// if some file path was not valid in windows
|
|
362
|
+
return res(getErrorMessage());
|
|
363
|
+
}
|
|
364
|
+
else {
|
|
365
|
+
return res({ status: 'success' });
|
|
366
|
+
}
|
|
367
|
+
});
|
|
368
|
+
_childProcess.on('error', async (error) => {
|
|
369
|
+
if (error.code === 'EBADF') {
|
|
370
|
+
return res({
|
|
371
|
+
status: 'error',
|
|
372
|
+
message: 'Unable to launch editor. This commonly happens when running in a containerized or server environment without terminal access.',
|
|
373
|
+
});
|
|
374
|
+
}
|
|
375
|
+
return res({ status: 'error', message: error.message });
|
|
376
|
+
});
|
|
377
|
+
});
|
|
378
|
+
}
|
|
379
|
+
//# sourceMappingURL=launch-editor.server.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"launch-editor.server.js","sourceRoot":"","sources":["../../src/launch-editor.server.ts"],"names":[],"mappings":"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","sourcesContent":["// copied (and barely modified) from create-react-app:\n// https://github.com/facebook/create-react-app/blob/d960b9e38c062584ff6cfb1a70e1512509a966e7/packages/react-dev-utils/launchEditor.js\n\nimport child_process from 'child_process'\nimport fs from 'fs'\nimport os from 'os'\nimport path from 'path'\nimport fsExtra from 'fs-extra'\nimport shellQuote from 'shell-quote'\nimport { getRelativePath } from './apps.server.js'\n\nfunction readablePath(filePath: string = '') {\n\tconst relative = getRelativePath(filePath)\n\tconst name = path.basename(relative)\n\tconst dir = path.dirname(relative)\n\treturn `'${name}' from:\\n'${dir}'`\n}\n\nfunction isTerminalEditor(editor: string) {\n\tswitch (editor) {\n\t\tcase 'vim':\n\t\tcase 'emacs':\n\t\tcase 'nano':\n\t\t\treturn true\n\t}\n\treturn false\n}\n\n// Map from full process name to binary that starts the process\n// We can't just re-use full process name, because it will spawn a new instance\n// of the app every time\nconst COMMON_EDITORS_OSX = {\n\t'/Applications/Atom.app/Contents/MacOS/Atom': 'atom',\n\t'/Applications/Atom Beta.app/Contents/MacOS/Atom Beta':\n\t\t'/Applications/Atom Beta.app/Contents/MacOS/Atom Beta',\n\t'/Applications/Brackets.app/Contents/MacOS/Brackets': 'brackets',\n\t'/Applications/Sublime Text.app/Contents/MacOS/Sublime Text':\n\t\t'/Applications/Sublime Text.app/Contents/SharedSupport/bin/subl',\n\t'/Applications/Sublime Text Dev.app/Contents/MacOS/Sublime Text':\n\t\t'/Applications/Sublime Text Dev.app/Contents/SharedSupport/bin/subl',\n\t'/Applications/Sublime Text 2.app/Contents/MacOS/Sublime Text 2':\n\t\t'/Applications/Sublime Text 2.app/Contents/SharedSupport/bin/subl',\n\t'/Applications/Cursor.app/Contents/MacOS/Cursor': 'cursor',\n\t'/Applications/Visual Studio Code.app/Contents/MacOS/Electron': 'code',\n\t'/Applications/Visual Studio Code - Insiders.app/Contents/MacOS/Electron':\n\t\t'code-insiders',\n\t'/Applications/VSCodium.app/Contents/MacOS/Electron': 'vscodium',\n\t'/Applications/AppCode.app/Contents/MacOS/appcode':\n\t\t'/Applications/AppCode.app/Contents/MacOS/appcode',\n\t'/Applications/CLion.app/Contents/MacOS/clion':\n\t\t'/Applications/CLion.app/Contents/MacOS/clion',\n\t'/Applications/IntelliJ IDEA.app/Contents/MacOS/idea':\n\t\t'/Applications/IntelliJ IDEA.app/Contents/MacOS/idea',\n\t'/Applications/PhpStorm.app/Contents/MacOS/phpstorm':\n\t\t'/Applications/PhpStorm.app/Contents/MacOS/phpstorm',\n\t'/Applications/PyCharm.app/Contents/MacOS/pycharm':\n\t\t'/Applications/PyCharm.app/Contents/MacOS/pycharm',\n\t'/Applications/PyCharm CE.app/Contents/MacOS/pycharm':\n\t\t'/Applications/PyCharm CE.app/Contents/MacOS/pycharm',\n\t'/Applications/RubyMine.app/Contents/MacOS/rubymine':\n\t\t'/Applications/RubyMine.app/Contents/MacOS/rubymine',\n\t'/Applications/WebStorm.app/Contents/MacOS/webstorm':\n\t\t'/Applications/WebStorm.app/Contents/MacOS/webstorm',\n\t'/Applications/MacVim.app/Contents/MacOS/MacVim': 'mvim',\n\t'/Applications/GoLand.app/Contents/MacOS/goland':\n\t\t'/Applications/GoLand.app/Contents/MacOS/goland',\n\t'/Applications/Rider.app/Contents/MacOS/rider':\n\t\t'/Applications/Rider.app/Contents/MacOS/rider',\n\t'/Applications/Zed/Zed.app/Contents/MacOS/zed': 'zed',\n} as const\n\nconst COMMON_EDITORS_LINUX = {\n\tatom: 'atom',\n\tBrackets: 'brackets',\n\tcursor: 'cursor',\n\tcode: 'code',\n\t'code-insiders': 'code-insiders',\n\tvscodium: 'vscodium',\n\temacs: 'emacs',\n\tgvim: 'gvim',\n\t'idea.sh': 'idea',\n\t'phpstorm.sh': 'phpstorm',\n\t'pycharm.sh': 'pycharm',\n\t'rubymine.sh': 'rubymine',\n\tsublime_text: 'sublime_text',\n\tvim: 'vim',\n\t'webstorm.sh': 'webstorm',\n\t'goland.sh': 'goland',\n\t'rider.sh': 'rider',\n\tzed: 'zed',\n}\n\nconst COMMON_EDITORS_WIN = [\n\t'Brackets.exe',\n\t'Cursor.exe',\n\t'Code.exe',\n\t'Code - Insiders.exe',\n\t'VSCodium.exe',\n\t'atom.exe',\n\t'sublime_text.exe',\n\t'notepad++.exe',\n\t'clion.exe',\n\t'clion64.exe',\n\t'idea.exe',\n\t'idea64.exe',\n\t'phpstorm.exe',\n\t'phpstorm64.exe',\n\t'pycharm.exe',\n\t'pycharm64.exe',\n\t'rubymine.exe',\n\t'rubymine64.exe',\n\t'webstorm.exe',\n\t'webstorm64.exe',\n\t'goland.exe',\n\t'goland64.exe',\n\t'rider.exe',\n\t'rider64.exe',\n\t'zed.exe',\n]\n\n// Transpiled version of: /^([A-Za-z]:[/\\\\])?[\\p{L}0-9/.\\-_\\\\]+$/u\n// Non-transpiled version requires support for Unicode property regex. Allows\n// alphanumeric characters, periods, dashes, slashes, and underscores.\nconst WINDOWS_FILE_NAME_WHITELIST =\n\t/^([A-Za-z]:[/\\\\])?(?:[\\x2D-9A-Z\\\\_a-z\\xAA\\xB5\\xBA\\xC0-\\xD6\\xD8-\\xF6\\xF8-\\u02C1\\u02C6-\\u02D1\\u02E0-\\u02E4\\u02EC\\u02EE\\u0370-\\u0374\\u0376\\u0377\\u037A-\\u037D\\u037F\\u0386\\u0388-\\u038A\\u038C\\u038E-\\u03A1\\u03A3-\\u03F5\\u03F7-\\u0481\\u048A-\\u052F\\u0531-\\u0556\\u0559\\u0560-\\u0588\\u05D0-\\u05EA\\u05EF-\\u05F2\\u0620-\\u064A\\u066E\\u066F\\u0671-\\u06D3\\u06D5\\u06E5\\u06E6\\u06EE\\u06EF\\u06FA-\\u06FC\\u06FF\\u0710\\u0712-\\u072F\\u074D-\\u07A5\\u07B1\\u07CA-\\u07EA\\u07F4\\u07F5\\u07FA\\u0800-\\u0815\\u081A\\u0824\\u0828\\u0840-\\u0858\\u0860-\\u086A\\u08A0-\\u08B4\\u08B6-\\u08BD\\u0904-\\u0939\\u093D\\u0950\\u0958-\\u0961\\u0971-\\u0980\\u0985-\\u098C\\u098F\\u0990\\u0993-\\u09A8\\u09AA-\\u09B0\\u09B2\\u09B6-\\u09B9\\u09BD\\u09CE\\u09DC\\u09DD\\u09DF-\\u09E1\\u09F0\\u09F1\\u09FC\\u0A05-\\u0A0A\\u0A0F\\u0A10\\u0A13-\\u0A28\\u0A2A-\\u0A30\\u0A32\\u0A33\\u0A35\\u0A36\\u0A38\\u0A39\\u0A59-\\u0A5C\\u0A5E\\u0A72-\\u0A74\\u0A85-\\u0A8D\\u0A8F-\\u0A91\\u0A93-\\u0AA8\\u0AAA-\\u0AB0\\u0AB2\\u0AB3\\u0AB5-\\u0AB9\\u0ABD\\u0AD0\\u0AE0\\u0AE1\\u0AF9\\u0B05-\\u0B0C\\u0B0F\\u0B10\\u0B13-\\u0B28\\u0B2A-\\u0B30\\u0B32\\u0B33\\u0B35-\\u0B39\\u0B3D\\u0B5C\\u0B5D\\u0B5F-\\u0B61\\u0B71\\u0B83\\u0B85-\\u0B8A\\u0B8E-\\u0B90\\u0B92-\\u0B95\\u0B99\\u0B9A\\u0B9C\\u0B9E\\u0B9F\\u0BA3\\u0BA4\\u0BA8-\\u0BAA\\u0BAE-\\u0BB9\\u0BD0\\u0C05-\\u0C0C\\u0C0E-\\u0C10\\u0C12-\\u0C28\\u0C2A-\\u0C39\\u0C3D\\u0C58-\\u0C5A\\u0C60\\u0C61\\u0C80\\u0C85-\\u0C8C\\u0C8E-\\u0C90\\u0C92-\\u0CA8\\u0CAA-\\u0CB3\\u0CB5-\\u0CB9\\u0CBD\\u0CDE\\u0CE0\\u0CE1\\u0CF1\\u0CF2\\u0D05-\\u0D0C\\u0D0E-\\u0D10\\u0D12-\\u0D3A\\u0D3D\\u0D4E\\u0D54-\\u0D56\\u0D5F-\\u0D61\\u0D7A-\\u0D7F\\u0D85-\\u0D96\\u0D9A-\\u0DB1\\u0DB3-\\u0DBB\\u0DBD\\u0DC0-\\u0DC6\\u0E01-\\u0E30\\u0E32\\u0E33\\u0E40-\\u0E46\\u0E81\\u0E82\\u0E84\\u0E87\\u0E88\\u0E8A\\u0E8D\\u0E94-\\u0E97\\u0E99-\\u0E9F\\u0EA1-\\u0EA3\\u0EA5\\u0EA7\\u0EAA\\u0EAB\\u0EAD-\\u0EB0\\u0EB2\\u0EB3\\u0EBD\\u0EC0-\\u0EC4\\u0EC6\\u0EDC-\\u0EDF\\u0F00\\u0F40-\\u0F47\\u0F49-\\u0F6C\\u0F88-\\u0F8C\\u1000-\\u102A\\u103F\\u1050-\\u1055\\u105A-\\u105D\\u1061\\u1065\\u1066\\u106E-\\u1070\\u1075-\\u1081\\u108E\\u10A0-\\u10C5\\u10C7\\u10CD\\u10D0-\\u10FA\\u10FC-\\u1248\\u124A-\\u124D\\u1250-\\u1256\\u1258\\u125A-\\u125D\\u1260-\\u1288\\u128A-\\u128D\\u1290-\\u12B0\\u12B2-\\u12B5\\u12B8-\\u12BE\\u12C0\\u12C2-\\u12C5\\u12C8-\\u12D6\\u12D8-\\u1310\\u1312-\\u1315\\u1318-\\u135A\\u1380-\\u138F\\u13A0-\\u13F5\\u13F8-\\u13FD\\u1401-\\u166C\\u166F-\\u167F\\u1681-\\u169A\\u16A0-\\u16EA\\u16F1-\\u16F8\\u1700-\\u170C\\u170E-\\u1711\\u1720-\\u1731\\u1740-\\u1751\\u1760-\\u176C\\u176E-\\u1770\\u1780-\\u17B3\\u17D7\\u17DC\\u1820-\\u1878\\u1880-\\u1884\\u1887-\\u18A8\\u18AA\\u18B0-\\u18F5\\u1900-\\u191E\\u1950-\\u196D\\u1970-\\u1974\\u1980-\\u19AB\\u19B0-\\u19C9\\u1A00-\\u1A16\\u1A20-\\u1A54\\u1AA7\\u1B05-\\u1B33\\u1B45-\\u1B4B\\u1B83-\\u1BA0\\u1BAE\\u1BAF\\u1BBA-\\u1BE5\\u1C00-\\u1C23\\u1C4D-\\u1C4F\\u1C5A-\\u1C7D\\u1C80-\\u1C88\\u1C90-\\u1CBA\\u1CBD-\\u1CBF\\u1CE9-\\u1CEC\\u1CEE-\\u1CF1\\u1CF5\\u1CF6\\u1D00-\\u1DBF\\u1E00-\\u1F15\\u1F18-\\u1F1D\\u1F20-\\u1F45\\u1F48-\\u1F4D\\u1F50-\\u1F57\\u1F59\\u1F5B\\u1F5D\\u1F5F-\\u1F7D\\u1F80-\\u1FB4\\u1FB6-\\u1FBC\\u1FBE\\u1FC2-\\u1FC4\\u1FC6-\\u1FCC\\u1FD0-\\u1FD3\\u1FD6-\\u1FDB\\u1FE0-\\u1FEC\\u1FF2-\\u1FF4\\u1FF6-\\u1FFC\\u2071\\u207F\\u2090-\\u209C\\u2102\\u2107\\u210A-\\u2113\\u2115\\u2119-\\u211D\\u2124\\u2126\\u2128\\u212A-\\u212D\\u212F-\\u2139\\u213C-\\u213F\\u2145-\\u2149\\u214E\\u2183\\u2184\\u2C00-\\u2C2E\\u2C30-\\u2C5E\\u2C60-\\u2CE4\\u2CEB-\\u2CEE\\u2CF2\\u2CF3\\u2D00-\\u2D25\\u2D27\\u2D2D\\u2D30-\\u2D67\\u2D6F\\u2D80-\\u2D96\\u2DA0-\\u2DA6\\u2DA8-\\u2DAE\\u2DB0-\\u2DB6\\u2DB8-\\u2DBE\\u2DC0-\\u2DC6\\u2DC8-\\u2DCE\\u2DD0-\\u2DD6\\u2DD8-\\u2DDE\\u2E2F\\u3005\\u3006\\u3031-\\u3035\\u303B\\u303C\\u3041-\\u3096\\u309D-\\u309F\\u30A1-\\u30FA\\u30FC-\\u30FF\\u3105-\\u312F\\u3131-\\u318E\\u31A0-\\u31BA\\u31F0-\\u31FF\\u3400-\\u4DB5\\u4E00-\\u9FEF\\uA000-\\uA48C\\uA4D0-\\uA4FD\\uA500-\\uA60C\\uA610-\\uA61F\\uA62A\\uA62B\\uA640-\\uA66E\\uA67F-\\uA69D\\uA6A0-\\uA6E5\\uA717-\\uA71F\\uA722-\\uA788\\uA78B-\\uA7B9\\uA7F7-\\uA801\\uA803-\\uA805\\uA807-\\uA80A\\uA80C-\\uA822\\uA840-\\uA873\\uA882-\\uA8B3\\uA8F2-\\uA8F7\\uA8FB\\uA8FD\\uA8FE\\uA90A-\\uA925\\uA930-\\uA946\\uA960-\\uA97C\\uA984-\\uA9B2\\uA9CF\\uA9E0-\\uA9E4\\uA9E6-\\uA9EF\\uA9FA-\\uA9FE\\uAA00-\\uAA28\\uAA40-\\uAA42\\uAA44-\\uAA4B\\uAA60-\\uAA76\\uAA7A\\uAA7E-\\uAAAF\\uAAB1\\uAAB5\\uAAB6\\uAAB9-\\uAABD\\uAAC0\\uAAC2\\uAADB-\\uAADD\\uAAE0-\\uAAEA\\uAAF2-\\uAAF4\\uAB01-\\uAB06\\uAB09-\\uAB0E\\uAB11-\\uAB16\\uAB20-\\uAB26\\uAB28-\\uAB2E\\uAB30-\\uAB5A\\uAB5C-\\uAB65\\uAB70-\\uABE2\\uAC00-\\uD7A3\\uD7B0-\\uD7C6\\uD7CB-\\uD7FB\\uF900-\\uFA6D\\uFA70-\\uFAD9\\uFB00-\\uFB06\\uFB13-\\uFB17\\uFB1D\\uFB1F-\\uFB28\\uFB2A-\\uFB36\\uFB38-\\uFB3C\\uFB3E\\uFB40\\uFB41\\uFB43\\uFB44\\uFB46-\\uFBB1\\uFBD3-\\uFD3D\\uFD50-\\uFD8F\\uFD92-\\uFDC7\\uFDF0-\\uFDFB\\uFE70-\\uFE74\\uFE76-\\uFEFC\\uFF21-\\uFF3A\\uFF41-\\uFF5A\\uFF66-\\uFFBE\\uFFC2-\\uFFC7\\uFFCA-\\uFFCF\\uFFD2-\\uFFD7\\uFFDA-\\uFFDC]|\\uD800[\\uDC00-\\uDC0B\\uDC0D-\\uDC26\\uDC28-\\uDC3A\\uDC3C\\uDC3D\\uDC3F-\\uDC4D\\uDC50-\\uDC5D\\uDC80-\\uDCFA\\uDE80-\\uDE9C\\uDEA0-\\uDED0\\uDF00-\\uDF1F\\uDF2D-\\uDF40\\uDF42-\\uDF49\\uDF50-\\uDF75\\uDF80-\\uDF9D\\uDFA0-\\uDFC3\\uDFC8-\\uDFCF]|\\uD801[\\uDC00-\\uDC9D\\uDCB0-\\uDCD3\\uDCD8-\\uDCFB\\uDD00-\\uDD27\\uDD30-\\uDD63\\uDE00-\\uDF36\\uDF40-\\uDF55\\uDF60-\\uDF67]|\\uD802[\\uDC00-\\uDC05\\uDC08\\uDC0A-\\uDC35\\uDC37\\uDC38\\uDC3C\\uDC3F-\\uDC55\\uDC60-\\uDC76\\uDC80-\\uDC9E\\uDCE0-\\uDCF2\\uDCF4\\uDCF5\\uDD00-\\uDD15\\uDD20-\\uDD39\\uDD80-\\uDDB7\\uDDBE\\uDDBF\\uDE00\\uDE10-\\uDE13\\uDE15-\\uDE17\\uDE19-\\uDE35\\uDE60-\\uDE7C\\uDE80-\\uDE9C\\uDEC0-\\uDEC7\\uDEC9-\\uDEE4\\uDF00-\\uDF35\\uDF40-\\uDF55\\uDF60-\\uDF72\\uDF80-\\uDF91]|\\uD803[\\uDC00-\\uDC48\\uDC80-\\uDCB2\\uDCC0-\\uDCF2\\uDD00-\\uDD23\\uDF00-\\uDF1C\\uDF27\\uDF30-\\uDF45]|\\uD804[\\uDC03-\\uDC37\\uDC83-\\uDCAF\\uDCD0-\\uDCE8\\uDD03-\\uDD26\\uDD44\\uDD50-\\uDD72\\uDD76\\uDD83-\\uDDB2\\uDDC1-\\uDDC4\\uDDDA\\uDDDC\\uDE00-\\uDE11\\uDE13-\\uDE2B\\uDE80-\\uDE86\\uDE88\\uDE8A-\\uDE8D\\uDE8F-\\uDE9D\\uDE9F-\\uDEA8\\uDEB0-\\uDEDE\\uDF05-\\uDF0C\\uDF0F\\uDF10\\uDF13-\\uDF28\\uDF2A-\\uDF30\\uDF32\\uDF33\\uDF35-\\uDF39\\uDF3D\\uDF50\\uDF5D-\\uDF61]|\\uD805[\\uDC00-\\uDC34\\uDC47-\\uDC4A\\uDC80-\\uDCAF\\uDCC4\\uDCC5\\uDCC7\\uDD80-\\uDDAE\\uDDD8-\\uDDDB\\uDE00-\\uDE2F\\uDE44\\uDE80-\\uDEAA\\uDF00-\\uDF1A]|\\uD806[\\uDC00-\\uDC2B\\uDCA0-\\uDCDF\\uDCFF\\uDE00\\uDE0B-\\uDE32\\uDE3A\\uDE50\\uDE5C-\\uDE83\\uDE86-\\uDE89\\uDE9D\\uDEC0-\\uDEF8]|\\uD807[\\uDC00-\\uDC08\\uDC0A-\\uDC2E\\uDC40\\uDC72-\\uDC8F\\uDD00-\\uDD06\\uDD08\\uDD09\\uDD0B-\\uDD30\\uDD46\\uDD60-\\uDD65\\uDD67\\uDD68\\uDD6A-\\uDD89\\uDD98\\uDEE0-\\uDEF2]|\\uD808[\\uDC00-\\uDF99]|\\uD809[\\uDC80-\\uDD43]|[\\uD80C\\uD81C-\\uD820\\uD840-\\uD868\\uD86A-\\uD86C\\uD86F-\\uD872\\uD874-\\uD879][\\uDC00-\\uDFFF]|\\uD80D[\\uDC00-\\uDC2E]|\\uD811[\\uDC00-\\uDE46]|\\uD81A[\\uDC00-\\uDE38\\uDE40-\\uDE5E\\uDED0-\\uDEED\\uDF00-\\uDF2F\\uDF40-\\uDF43\\uDF63-\\uDF77\\uDF7D-\\uDF8F]|\\uD81B[\\uDE40-\\uDE7F\\uDF00-\\uDF44\\uDF50\\uDF93-\\uDF9F\\uDFE0\\uDFE1]|\\uD821[\\uDC00-\\uDFF1]|\\uD822[\\uDC00-\\uDEF2]|\\uD82C[\\uDC00-\\uDD1E\\uDD70-\\uDEFB]|\\uD82F[\\uDC00-\\uDC6A\\uDC70-\\uDC7C\\uDC80-\\uDC88\\uDC90-\\uDC99]|\\uD835[\\uDC00-\\uDC54\\uDC56-\\uDC9C\\uDC9E\\uDC9F\\uDCA2\\uDCA5\\uDCA6\\uDCA9-\\uDCAC\\uDCAE-\\uDCB9\\uDCBB\\uDCBD-\\uDCC3\\uDCC5-\\uDD05\\uDD07-\\uDD0A\\uDD0D-\\uDD14\\uDD16-\\uDD1C\\uDD1E-\\uDD39\\uDD3B-\\uDD3E\\uDD40-\\uDD44\\uDD46\\uDD4A-\\uDD50\\uDD52-\\uDEA5\\uDEA8-\\uDEC0\\uDEC2-\\uDEDA\\uDEDC-\\uDEFA\\uDEFC-\\uDF14\\uDF16-\\uDF34\\uDF36-\\uDF4E\\uDF50-\\uDF6E\\uDF70-\\uDF88\\uDF8A-\\uDFA8\\uDFAA-\\uDFC2\\uDFC4-\\uDFCB]|\\uD83A[\\uDC00-\\uDCC4\\uDD00-\\uDD43]|\\uD83B[\\uDE00-\\uDE03\\uDE05-\\uDE1F\\uDE21\\uDE22\\uDE24\\uDE27\\uDE29-\\uDE32\\uDE34-\\uDE37\\uDE39\\uDE3B\\uDE42\\uDE47\\uDE49\\uDE4B\\uDE4D-\\uDE4F\\uDE51\\uDE52\\uDE54\\uDE57\\uDE59\\uDE5B\\uDE5D\\uDE5F\\uDE61\\uDE62\\uDE64\\uDE67-\\uDE6A\\uDE6C-\\uDE72\\uDE74-\\uDE77\\uDE79-\\uDE7C\\uDE7E\\uDE80-\\uDE89\\uDE8B-\\uDE9B\\uDEA1-\\uDEA3\\uDEA5-\\uDEA9\\uDEAB-\\uDEBB]|\\uD869[\\uDC00-\\uDED6\\uDF00-\\uDFFF]|\\uD86D[\\uDC00-\\uDF34\\uDF40-\\uDFFF]|\\uD86E[\\uDC00-\\uDC1D\\uDC20-\\uDFFF]|\\uD873[\\uDC00-\\uDEA1\\uDEB0-\\uDFFF]|\\uD87A[\\uDC00-\\uDFE0]|\\uD87E[\\uDC00-\\uDE1D])+$/\n\nfunction addWorkspaceToArgumentsIfExists(\n\targs: Array<string>,\n\tworkspace: string | null,\n) {\n\tif (workspace) {\n\t\targs.unshift(workspace)\n\t}\n\treturn args\n}\n\nfunction getArgumentsForLineNumber(\n\teditor: string,\n\tfileName: string,\n\tlineNumber: number,\n\tcolNumber: number | undefined,\n\tworkspace: string | null,\n) {\n\tconst editorBasename = path.basename(editor).replace(/\\.(exe|cmd|bat)$/i, '')\n\tswitch (editorBasename) {\n\t\tcase 'atom':\n\t\tcase 'Atom':\n\t\tcase 'Atom Beta':\n\t\tcase 'subl':\n\t\tcase 'sublime':\n\t\tcase 'sublime_text':\n\t\t\treturn [`${fileName}:${lineNumber}:${colNumber}`]\n\t\tcase 'wstorm':\n\t\tcase 'charm':\n\t\t\treturn [`${fileName}:${lineNumber}`]\n\t\tcase 'notepad++':\n\t\t\treturn [`-n${lineNumber}`, `-c${colNumber}`, fileName]\n\t\tcase 'vim':\n\t\tcase 'mvim':\n\t\tcase 'joe':\n\t\tcase 'gvim':\n\t\t\treturn [`+${lineNumber}`, fileName]\n\t\tcase 'emacs':\n\t\tcase 'emacsclient':\n\t\t\treturn [`+${lineNumber}:${colNumber}`, fileName]\n\t\tcase 'rmate':\n\t\tcase 'mate':\n\t\tcase 'mine':\n\t\t\treturn ['--line', lineNumber, fileName]\n\t\tcase 'cursor':\n\t\tcase 'code':\n\t\tcase 'Code':\n\t\tcase 'code-insiders':\n\t\tcase 'Code - Insiders':\n\t\tcase 'vscodium':\n\t\tcase 'VSCodium':\n\t\t\treturn addWorkspaceToArgumentsIfExists(\n\t\t\t\t['-g', `${fileName}:${lineNumber}:${colNumber}`],\n\t\t\t\tworkspace,\n\t\t\t)\n\t\tcase 'appcode':\n\t\tcase 'clion':\n\t\tcase 'clion64':\n\t\tcase 'idea':\n\t\tcase 'idea64':\n\t\tcase 'phpstorm':\n\t\tcase 'phpstorm64':\n\t\tcase 'pycharm':\n\t\tcase 'pycharm64':\n\t\tcase 'rubymine':\n\t\tcase 'rubymine64':\n\t\tcase 'webstorm':\n\t\tcase 'webstorm64':\n\t\tcase 'goland':\n\t\tcase 'goland64':\n\t\tcase 'rider':\n\t\tcase 'rider64':\n\t\t\treturn addWorkspaceToArgumentsIfExists(\n\t\t\t\t['--line', lineNumber.toString(), fileName],\n\t\t\t\tworkspace,\n\t\t\t)\n\t}\n\n\t// For all others, drop the lineNumber until we have\n\t// a mapping above, since providing the lineNumber incorrectly\n\t// can result in errors or confusing behavior.\n\treturn [fileName]\n}\n\nfunction guessEditor(): Array<string | null> {\n\t// Explicit config always wins\n\tif (process.env.EPICSHOP_EDITOR) {\n\t\treturn shellQuote.parse(process.env.EPICSHOP_EDITOR).map((a) => String(a))\n\t}\n\n\t// We can find out which editor is currently running by:\n\t// `ps x` on macOS and Linux\n\t// `Get-Process` on Windows\n\ttry {\n\t\tif (process.platform === 'darwin') {\n\t\t\tconst output = child_process.execSync('ps x').toString()\n\t\t\tconst processNames = Object.keys(COMMON_EDITORS_OSX) as Array<\n\t\t\t\tkeyof typeof COMMON_EDITORS_OSX\n\t\t\t>\n\t\t\tfor (let i = 0; i < processNames.length; i++) {\n\t\t\t\tconst processName = processNames[i]\n\t\t\t\tif (processName && output.includes(processName)) {\n\t\t\t\t\tconst editor = COMMON_EDITORS_OSX[processName]\n\t\t\t\t\treturn [editor]\n\t\t\t\t}\n\t\t\t}\n\t\t} else if (process.platform === 'win32') {\n\t\t\t// Some processes need elevated rights to get its executable path.\n\t\t\t// Just filter them out upfront. This also saves 10-20ms on the command.\n\t\t\tconst output = child_process\n\t\t\t\t.execSync(\n\t\t\t\t\t'wmic process where \"executablepath is not null\" get executablepath',\n\t\t\t\t)\n\t\t\t\t.toString()\n\t\t\tconst runningProcesses = output.split('\\r\\n')\n\t\t\tfor (let i = 0; i < runningProcesses.length; i++) {\n\t\t\t\tconst processPath = runningProcesses[i]?.trim()\n\t\t\t\tif (!processPath) continue\n\t\t\t\tconst processName = path.basename(processPath)\n\t\t\t\tif (COMMON_EDITORS_WIN.includes(processName)) {\n\t\t\t\t\treturn [processPath]\n\t\t\t\t}\n\t\t\t}\n\t\t} else if (process.platform === 'linux') {\n\t\t\t// --no-heading No header line\n\t\t\t// x List all processes owned by you\n\t\t\t// -o comm Need only names column\n\t\t\tconst output = child_process\n\t\t\t\t.execSync('ps x --no-heading -o comm --sort=comm')\n\t\t\t\t.toString()\n\t\t\tconst processNames = Object.keys(COMMON_EDITORS_LINUX)\n\t\t\tfor (let i = 0; i < processNames.length; i++) {\n\t\t\t\tconst processName = processNames[i]\n\t\t\t\tif (!processName) continue\n\t\t\t\tif (output.includes(processName)) {\n\t\t\t\t\t// @ts-expect-error 🤷♂️ it's fine\n\t\t\t\t\treturn [COMMON_EDITORS_LINUX[processName]]\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t} catch {\n\t\t// Ignore...\n\t}\n\n\t// Last resort, use old skool env vars\n\tif (process.env.VISUAL) {\n\t\treturn [process.env.VISUAL]\n\t} else if (process.env.EDITOR) {\n\t\treturn [process.env.EDITOR]\n\t}\n\n\treturn [null]\n}\n\nlet _childProcess: ReturnType<typeof child_process.spawn> | null = null\nexport type Result =\n\t| { status: 'success' }\n\t| { status: 'error'; message: string }\nexport async function launchEditor(\n\tpathList: string[] | string,\n\tlineNumber: number = 1,\n\tcolNumber: number = 1,\n): Promise<Result> {\n\t// Sanitize lineNumber to prevent malicious use on win32\n\t// via: https://github.com/nodejs/node/blob/c3bb4b1aa5e907d489619fb43d233c3336bfc03d/lib/child_process.js#L333\n\t// and it should be a positive integer\n\tif (lineNumber && !(Number.isInteger(lineNumber) && lineNumber > 0)) {\n\t\treturn { status: 'error', message: 'lineNumber must be a positive integer' }\n\t}\n\n\t// colNumber is optional, but should be a positive integer too\n\t// default is 1\n\tif (colNumber && !(Number.isInteger(colNumber) && colNumber > 0)) {\n\t\tcolNumber = 1\n\t}\n\n\tconst editorInfo = guessEditor()\n\tconst editor = editorInfo[0]\n\tlet args = editorInfo.slice(1).filter(Boolean)\n\n\tif (!editor) {\n\t\treturn { status: 'error', message: 'No editor found' }\n\t}\n\n\tif (editor.toLowerCase() === 'none') {\n\t\treturn { status: 'error', message: 'Editor set to \"none\"' }\n\t}\n\n\tif (typeof pathList === 'string') {\n\t\tpathList = [pathList]\n\t}\n\n\ttype accumulator = {\n\t\tfileList: string[]\n\t\terrorsList: string[]\n\t}\n\n\tconst initArgs: accumulator = { fileList: [], errorsList: [] }\n\n\tconst { fileList, errorsList } = pathList.reduce(\n\t\t(acc: accumulator, fileName: string) => {\n\t\t\tif (\n\t\t\t\tprocess.platform === 'linux' &&\n\t\t\t\tfileName.startsWith('/mnt/') &&\n\t\t\t\t/Microsoft/i.test(os.release())\n\t\t\t) {\n\t\t\t\t// Assume WSL / \"Bash on Ubuntu on Windows\" is being used, and\n\t\t\t\t// that the file exists on the Windows file system.\n\t\t\t\t// `os.release()` is \"4.4.0-43-Microsoft\" in the current release\n\t\t\t\t// build of WSL, see: https://github.com/Microsoft/BashOnWindows/issues/423#issuecomment-221627364\n\t\t\t\t// When a Windows editor is specified, interop functionality can\n\t\t\t\t// handle the path translation, but only if a relative path is used.\n\t\t\t\tfileName = path.relative('', fileName)\n\t\t\t}\n\n\t\t\tconst fileExists = fs.existsSync(fileName)\n\t\t\t// cmd.exe on Windows is vulnerable to RCE attacks given a file name of the\n\t\t\t// form \"C:\\Users\\myusername\\Downloads\\& curl 172.21.93.52\". Use a whitelist\n\t\t\t// to validate user-provided file names. This doesn't cover the entire range\n\t\t\t// of valid file names but should cover almost all of them in practice.\n\t\t\t// if the file exists, then we're good.\n\t\t\tif (\n\t\t\t\t!fileExists &&\n\t\t\t\tprocess.platform === 'win32' &&\n\t\t\t\t!WINDOWS_FILE_NAME_WHITELIST.test(fileName)\n\t\t\t) {\n\t\t\t\tacc.errorsList.push(fileName)\n\t\t\t} else {\n\t\t\t\tif (!fileExists) {\n\t\t\t\t\tfsExtra.ensureDirSync(path.dirname(fileName))\n\t\t\t\t\tfsExtra.writeFileSync(fileName, '', 'utf8')\n\t\t\t\t}\n\n\t\t\t\tacc.fileList.push(fileName.trim())\n\t\t\t}\n\t\t\treturn acc\n\t\t},\n\t\tinitArgs,\n\t)\n\n\t// TODO: figure out how to send error messages as JSX from here...\n\tfunction getErrorMessage() {\n\t\tlet message: string\n\t\tif (errorsList.length) {\n\t\t\tconst readableName =\n\t\t\t\terrorsList.length === 1 ? readablePath(errorsList[0]) : 'some files'\n\t\t\tmessage = `Could not open ${readableName} in the editor.\\n\\nWhen running on Windows, file names are checked against a whitelist to protect against remote code execution attacks.\\nFile names may consist only of alphanumeric characters (all languages), periods, dashes, slashes, and underscores. Maybe you have your files in a folder that includes a space in the pathname? Rename the folder to remove the space and try again.`\n\t\t} else {\n\t\t\tmessage = 'pathList must contain at least one valid file path'\n\t\t}\n\t\treturn {\n\t\t\tstatus: 'error',\n\t\t\tmessage,\n\t\t} as Result\n\t}\n\n\tconst workspace = null\n\tif (lineNumber && fileList.length === 1) {\n\t\tconst fileName = fileList[0]\n\t\tif (!fileName) {\n\t\t\treturn getErrorMessage()\n\t\t}\n\t\targs = args.concat(\n\t\t\tgetArgumentsForLineNumber(\n\t\t\t\teditor,\n\t\t\t\tfileName,\n\t\t\t\tlineNumber,\n\t\t\t\tcolNumber,\n\t\t\t\tworkspace,\n\t\t\t)\n\t\t\t\t.filter(Boolean)\n\t\t\t\t.map(String),\n\t\t)\n\t} else {\n\t\tconst argList = fileList.filter(Boolean)\n\t\tif (!argList.length) {\n\t\t\treturn getErrorMessage()\n\t\t}\n\t\targs.push(...argList)\n\t}\n\n\tif (_childProcess && isTerminalEditor(editor)) {\n\t\t// There's an existing editor process already and it's attached\n\t\t// to the terminal, so go kill it. Otherwise two separate editor\n\t\t// instances attach to the stdin/stdout which gets confusing.\n\t\t_childProcess.kill('SIGKILL')\n\t}\n\n\treturn new Promise((res) => {\n\t\tif (process.platform === 'win32') {\n\t\t\t// On Windows, launch the editor in a shell because spawn can only\n\t\t\t// launch .exe files.\n\t\t\t_childProcess = child_process.spawn(\n\t\t\t\t'cmd.exe',\n\t\t\t\t['/C', editor].concat(args).filter(Boolean),\n\t\t\t\t{ stdio: ['inherit', 'inherit', 'pipe'] },\n\t\t\t)\n\t\t} else {\n\t\t\t_childProcess = child_process.spawn(editor, args, {\n\t\t\t\tstdio: ['inherit', 'inherit', 'pipe'],\n\t\t\t})\n\t\t}\n\t\t_childProcess.stderr?.on('data', (data: string | Uint8Array) => {\n\t\t\tconst message = String(data)\n\t\t\t// Filter out the specific error message for environment variable issues\n\t\t\tif (!message.includes('Node.js environment variables are disabled')) {\n\t\t\t\tprocess.stderr.write(data) // Only write non-filtered messages to stderr\n\t\t\t}\n\t\t})\n\t\t_childProcess.on('exit', async (errorCode) => {\n\t\t\t_childProcess = null\n\n\t\t\tif (errorCode) {\n\t\t\t\tconst readableName =\n\t\t\t\t\tfileList.length === 1 ? readablePath(fileList[0]) : 'some files'\n\t\t\t\treturn res({\n\t\t\t\t\tstatus: 'error',\n\t\t\t\t\tmessage: `Could not open ${readableName} in the editor.\\n\\nThe editor process exited with an error code (${errorCode}).`,\n\t\t\t\t})\n\t\t\t} else if (errorsList.length) {\n\t\t\t\t// show error message even when the editor was opened successfully,\n\t\t\t\t// if some file path was not valid in windows\n\t\t\t\treturn res(getErrorMessage())\n\t\t\t} else {\n\t\t\t\treturn res({ status: 'success' })\n\t\t\t}\n\t\t})\n\n\t\t_childProcess.on('error', async (error: Error & { code?: string }) => {\n\t\t\tif (error.code === 'EBADF') {\n\t\t\t\treturn res({\n\t\t\t\t\tstatus: 'error',\n\t\t\t\t\tmessage:\n\t\t\t\t\t\t'Unable to launch editor. This commonly happens when running in a containerized or server environment without terminal access.',\n\t\t\t\t})\n\t\t\t}\n\t\t\treturn res({ status: 'error', message: error.message })\n\t\t})\n\t})\n}\n"]}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@epic-web/workshop-utils",
|
|
3
|
-
"version": "6.
|
|
3
|
+
"version": "6.39.0",
|
|
4
4
|
"publishConfig": {
|
|
5
5
|
"access": "public"
|
|
6
6
|
},
|
|
@@ -21,6 +21,7 @@
|
|
|
21
21
|
"./config.server": "./src/config.server.ts",
|
|
22
22
|
"./db.server": "./src/db.server.ts",
|
|
23
23
|
"./data-storage.server": "./src/data-storage.server.ts",
|
|
24
|
+
"./launch-editor.server": "./src/launch-editor.server.ts",
|
|
24
25
|
"./timing.server": "./src/timing.server.ts",
|
|
25
26
|
"./modified-time.server": "./src/modified-time.server.ts",
|
|
26
27
|
"./compile-mdx.server": "./src/compile-mdx.server.ts",
|
|
@@ -93,6 +94,12 @@
|
|
|
93
94
|
"default": "./dist/esm/data-storage.server.js"
|
|
94
95
|
}
|
|
95
96
|
},
|
|
97
|
+
"./launch-editor.server": {
|
|
98
|
+
"import": {
|
|
99
|
+
"types": "./dist/esm/launch-editor.server.d.ts",
|
|
100
|
+
"default": "./dist/esm/launch-editor.server.js"
|
|
101
|
+
}
|
|
102
|
+
},
|
|
96
103
|
"./timing.server": {
|
|
97
104
|
"import": {
|
|
98
105
|
"types": "./dist/esm/timing.server.d.ts",
|
|
@@ -235,6 +242,7 @@
|
|
|
235
242
|
"remark": "^15.0.1",
|
|
236
243
|
"remark-emoji": "^5.0.1",
|
|
237
244
|
"remark-gfm": "^4.0.1",
|
|
245
|
+
"shell-quote": "^1.8.3",
|
|
238
246
|
"shiki": "^3.7.0",
|
|
239
247
|
"unified": "^11.0.5",
|
|
240
248
|
"unist-util-remove-position": "^5.0.0",
|
|
@@ -247,6 +255,7 @@
|
|
|
247
255
|
"@types/node": "^24.0.10",
|
|
248
256
|
"@types/react": "^19.1.8",
|
|
249
257
|
"@types/react-dom": "^19.1.6",
|
|
258
|
+
"@types/shell-quote": "^1.7.5",
|
|
250
259
|
"tshy": "^3.0.2",
|
|
251
260
|
"vitest": "^3.2.4"
|
|
252
261
|
},
|