From 15ccd994ec1ae48a454ce8c5cc43f48eee7a7a47 Mon Sep 17 00:00:00 2001 From: Keith Cagney Date: Thu, 2 Jan 2020 12:30:24 -0500 Subject: [PATCH 1/3] Webview not working, has function to parse out package.json script, awaiting merge with child.process launcher --- dist/extension.js | 157 +++++++++++++++++++---------------------- dist/extension.js.map | 2 +- src/extension.ts | 160 ++++++++++++++++++++---------------------- 3 files changed, 149 insertions(+), 170 deletions(-) diff --git a/dist/extension.js b/dist/extension.js index 64d4598..91f983c 100644 --- a/dist/extension.js +++ b/dist/extension.js @@ -1029,19 +1029,9 @@ const url_1 = __webpack_require__(/*! url */ "url"); const path = __webpack_require__(/*! path */ "path"); const fs = __webpack_require__(/*! fs */ "fs"); const ps = __webpack_require__(/*! ps-node */ "./node_modules/ps-node/index.js"); -let PORT = 6006; -const host = 'localhost'; -// import * as express from 'express'; -// import { resolveCliPathFromVSCodeExecutablePath } from 'vscode-test'; -// const server = express(); function activate(context) { - // server.get('/', (req, res) => { - // vscode.window.showInformationMessage('Aesop server online'); - // res.end(); - // }); - // server.listen(PORT); - //set the extension context equal to "aesop is running" - vscode.commands.executeCommand("setContext", "is-running-aesop", true); + let PORT = 6006; + const host = 'localhost'; //create disposable variable type, registers awaken command & opens webview let disposable = vscode.commands.registerCommand('extension.aesopAwaken', () => { //define a path to the root working directory of the user @@ -1062,100 +1052,67 @@ function activate(context) { vscode.window.showErrorMessage(`Failed looking for running Node processes. Error: ${err}`); } else { + let foundSb = false; //if the process lookup was able to find running processes, iterate through to review them - //potential problem: we may also need to account for running processes given no port flag resultList.forEach((process) => { // ---> OUTPUT LOGGER <--- // fs.writeFile(path.join(rootDir, 'YOLO.txt'), `Here is the JSON-stringified version of a process:\n${JSON.stringify(process)}\n`, (err) => { console.log(`Couldn't output process information to YOLO.txt: ${err}`); }); vscode.window.showInformationMessage('Check YOLO.txt for output information'); //check if any running processes are using the start-storybook script if (process.arguments[0].includes('storybook')) { + foundSb = true; //stretch goal: check for multiple instances of storybook and reconcile - // ---> OUTPUT LOGGER <--- // - fs.appendFile(path.join(rootDir, 'YOLO.txt'), `This process matches for 'storybook'search string:\n - PID: ${process.pid}, COMMAND:${process.command}, ARGUMENTS: ${process.arguments}\n`, (err) => { console.log(err); }); //if so, extract port number and use that value to populate the webview with that contents - const sbProcess = process.arguments; - const portFlag = '-p'; - const pFlagIndex = sbProcess.indexOf(portFlag); + const pFlagIndex = process.arguments.indexOf('-p'); if (pFlagIndex !== -1) { PORT = Number(process.arguments[pFlagIndex + 1]); } + // ---> OUTPUT LOGGER <--- // + fs.appendFile(path.join(rootDir, 'YOLO.txt'), `This process matches for 'storybook'search string:\n + PID: ${process.pid}, COMMAND:${process.command}, ARGUMENTS: ${process.arguments}\n`, (err) => { console.log(err); }); + } + }); + if (foundSb === false) { + //if no processes match 'storybook', we will have to spin up the storybook server + //starts by extracting the existing storybook script in the package.json + fs.readFile(path.join(rootDir, 'package.json'), (err, data) => { + if (err) { + vscode.window.showErrorMessage(`Does this root folder contain a "package.json" file?`); + } else { - //if no processes match 'storybook', we will have to spin up the storybook server - //starts by extracting the existing storybook script in the package.json - fs.readFile(path.join(rootDir, 'package.json'), (err, data) => { - if (err) { - vscode.window.showErrorMessage(`Does this root folder contain a "package.json" file?`); + //enter the package.JSON file and retrieve its contents as a string + let packageJSONText = JSON.parse(data.toString()); + let storybookScript = packageJSONText.scripts.storybook; + // // ---> OUTPUT LOGGER <--- // + // fs.appendFile(path.join(rootDir, 'YOLO.txt'), `Here is the JSON parsed version:\n + // ${packageJSONText.scripts}\n + // ${packageJSONText.scripts.storybook}`, (err) => {console.log(err)}); + // // ---> OUTPUT LOGGER <--- // + // fs.appendFile(path.join(rootDir, 'YOLO.txt'), `Here is the full contents of the package.json file from the user's workspace folder:\n${packageJSONText}\n`, (err) => {console.log(err)}); + // // ---> OUTPUT LOGGER <--- // + // fs.appendFile(path.join(rootDir, 'YOLO.txt'), `This is what our readFile function (line 72) returns when it attempts to retrieve (line 82) the "storybook" script from your app's package.json:\n${retrievedScript}\n`, (err) => {console.log(err)}); + //iterate through that text string and parse out important flags + //it is more helpful to split it into an array separated by whitespace to grab these + let retrievedScriptArray = storybookScript.split(' '); + for (let i = 0; i < retrievedScriptArray.length; i++) { + //add flags + if (retrievedScriptArray[i] === '-p') { + PORT = parseInt(retrievedScriptArray[i + 1]); } - else { - //enter the package.JSON file and retrieve its contents as a string - let packageJSONText = data.toString(); - // ---> OUTPUT LOGGER <--- // - fs.appendFile(path.join(rootDir, 'YOLO.txt'), `Here is the full contents of the package.json file from the user's workspace folder:\n${packageJSONText}\n`, (err) => { console.log(err); }); - //find where the "storybook" script is defined - let targetScriptStartIndex = packageJSONText.indexOf(`\"storybook\"\:`) + 12; - //retrieve the value (i.e. the entire line of text) of the "storybook" script - let retrievedScript = packageJSONText.slice(targetScriptStartIndex, packageJSONText.indexOf(vscode.EndOfLine.toString())); - // ---> OUTPUT LOGGER <--- // - fs.appendFile(path.join(rootDir, 'YOLO.txt'), `This is what our readFile function (line 72) returns when it attempts to retrieve (line 82) the "storybook" script from your app's package.json:\n${retrievedScript}\n`, (err) => { console.log(err); }); - //iterate through that text string and parse out important flags - //it is more helpful to split it into an array separated by whitespace to grab these - let retrievedScriptAsArray = retrievedScript.split(' '); - for (let i = 0; i < retrievedScriptAsArray.length; i++) { - //add flags - if (retrievedScriptAsArray[i] === '-p') { - PORT = Number(retrievedScriptAsArray[i + 1]); - } - } - /* - vscode.tasks.registerTaskProvider('runStorybook', { - provideTasks(token?: vscode.CancellationToken) { - return [ - new vscode.Task({type: 'runStorybook'}, vscode.TaskScope.Workspace, - "Aesop Chronicle", "aesop", new vscode.ShellExecution(`npm run storybook --ci`)) - ]; - }, - resolveTask(task: vscode.Task, token?: vscode.CancellationToken) { - return task; - } - }); - - //define the script text to execute to the virtual terminal instance - const bootScript = `storybook --ci`; - const bootStorybook = new vscode.ProcessExecution(bootScript, {cwd: rootDir}); - - //now create a virtual terminal and execute our special npm script for it - //this first requires creating an eventEmitter that will fire that script - const scriptEmitter = new vscode.EventEmitter(); - - //we also define a slave process Pseudoterminal (allowing Aesop to control the terminal) - const pty: vscode.Pseudoterminal = { - onDidWrite: scriptEmitter.event, - open: () => scriptEmitter.fire(bootScript), - close: () => {}, - handleInput: data => new vscode.ShellExecution(data) - }; - - //should this just be an active terminal/shellExecution? - const virtualTerminal = vscode.window.createTerminal({name: 'sb-runner', pty}); - */ - } - }); + } } - } - }); + }); + } } }); } }); + //set the extension context equal to "aesop is running" + // vscode.commands.executeCommand("setContext", "is-running-aesop", true); //still inside our disposable variable, let's create the webview panel const panel = vscode.window.createWebviewPanel('aesop-sb', 'Aesop', vscode.ViewColumn.Two, { enableCommandUris: true, enableScripts: true, - portMapping: [ - { webviewPort: PORT, extensionHostPort: PORT } - ] }); panel.webview.html = ` @@ -1170,7 +1127,6 @@ function activate(context) { `; }); - //closes disposable context.subscriptions.push(disposable); } exports.activate = activate; @@ -1185,6 +1141,39 @@ to-do: figure out how to use a tsx rule in webpack to execute scripts signal babel to interpret this block as tsx, e.g. something like: //@tsx babel// + + + vscode.tasks.registerTaskProvider('runStorybook', { + provideTasks(token?: vscode.CancellationToken) { + return [ + new vscode.Task({type: 'runStorybook'}, vscode.TaskScope.Workspace, + "Aesop Chronicle", "aesop", new vscode.ShellExecution(`npm run storybook --ci`)) + ]; + }, + resolveTask(task: vscode.Task, token?: vscode.CancellationToken) { + return task; + } + }); + + //define the script text to execute to the virtual terminal instance + const bootScript = `storybook --ci`; + const bootStorybook = new vscode.ProcessExecution(bootScript, {cwd: rootDir}); + + //now create a virtual terminal and execute our special npm script for it + //this first requires creating an eventEmitter that will fire that script + const scriptEmitter = new vscode.EventEmitter(); + + //we also define a slave process Pseudoterminal (allowing Aesop to control the terminal) + const pty: vscode.Pseudoterminal = { + onDidWrite: scriptEmitter.event, + open: () => scriptEmitter.fire(bootScript), + close: () => {}, + handleInput: data => new vscode.ShellExecution(data) + }; + + //should this just be an active terminal/shellExecution? + const virtualTerminal = vscode.window.createTerminal({name: 'sb-runner', pty}); + //THIS WORKS, but we have no access to the DOM inside our webview// //now let's read SB's outputted index.html file, and parse out what we need fs.readFile(path.join(rootDir, '/node_modules/@storybook/core/dist/public/index.html'), (err, data) => { diff --git a/dist/extension.js.map b/dist/extension.js.map index 740b818..75c9805 100644 --- a/dist/extension.js.map +++ b/dist/extension.js.map @@ -1 +1 @@ -{"version":3,"sources":["../webpack/bootstrap",".././node_modules/connected-domain/index.js",".././node_modules/connected-domain/lib/connected-domain.js",".././node_modules/ps-node/index.js",".././node_modules/ps-node/lib/index.js",".././node_modules/table-parser/index.js",".././node_modules/table-parser/lib/index.js",".././src/extension.ts","../external \"child_process\"","../external \"fs\"","../external \"os\"","../external \"path\"","../external \"url\"","../external \"vscode\""],"names":[],"mappings":";;QAAA;QACA;;QAEA;QACA;;QAEA;QACA;QACA;QACA;QACA;QACA;QACA;QACA;QACA;QACA;;QAEA;QACA;;QAEA;QACA;;QAEA;QACA;QACA;;;QAGA;QACA;;QAEA;QACA;;QAEA;QACA;QACA;QACA,0CAA0C,gCAAgC;QAC1E;QACA;;QAEA;QACA;QACA;QACA,wDAAwD,kBAAkB;QAC1E;QACA,iDAAiD,cAAc;QAC/D;;QAEA;QACA;QACA;QACA;QACA;QACA;QACA;QACA;QACA;QACA;QACA;QACA,yCAAyC,iCAAiC;QAC1E,gHAAgH,mBAAmB,EAAE;QACrI;QACA;;QAEA;QACA;QACA;QACA,2BAA2B,0BAA0B,EAAE;QACvD,iCAAiC,eAAe;QAChD;QACA;QACA;;QAEA;QACA,sDAAsD,+DAA+D;;QAErH;QACA;;;QAGA;QACA;;;;;;;;;;;;AClFA,iBAAiB,mBAAO,EAAE,uFAAwB,G;;;;;;;;;;;ACAlD;AACA;AACA;;AAEA;AACA,WAAW,MAAM;AACjB,WAAW,SAAS;AACpB,WAAW,QAAQ;AACnB,YAAY,OAAO,GAAG,YAAY,2BAA2B,aAAa,sBAAsB,EAAE,qCAAqC;AACvI;AACA;;AAEA;;AAEA;AACA;AACA;;AAEA;AACA;AACA;;AAEA;AACA;;AAEA;AACA;AACA;AACA;;AAEA;;AAEA;;AAEA;;AAEA;AACA;;AAEA;AACA;AACA;;AAEA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;;AAEA;AACA;;AAEA;;AAEA;;AAEA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,iBAAiB;;AAEjB;AACA;AACA;AACA;AACA;AACA;AACA;AACA,SAAS;AACT,KAAK;;AAEL;AACA;AACA;AACA;AACA,6BAA6B;AAC7B;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;;AAEA;AACA;AACA;AACA;;AAEA;AACA;;;AAGA;;AAEA;AACA;AACA;AACA;;AAEA;;AAEA;AACA;AACA;;AAEA;AACA;AACA;;AAEA;AACA;AACA;;AAEA;AACA;AACA;AACA,SAAS;;AAET;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA,wBAAwB;AACxB;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;;AAEA;;AAEA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;;AAEA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;;AAEA;AACA;;AAEA;;AAEA;AACA;AACA;AACA,aAAa;;AAEb;;AAEA;AACA;AACA;AACA;;AAEA;AACA,E;;;;;;;;;;;AC/PA,iBAAiB,mBAAO,CAAC,kDAAO;;;;;;;;;;;;ACAhC,mBAAmB,mBAAO,CAAC,oCAAe;AAC1C;AACA,kBAAkB,mBAAO,CAAC,0DAAc;AACxC;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,gBAAgB,mBAAO,CAAC,cAAI;;AAE5B;AACA;AACA,UAAU;AACV,WAAW,SAAS;AACpB,WAAW,SAAS;AACpB,WAAW,YAAY;AACvB,WAAW,SAAS;AACpB;;AAEA;AACA;;AAEA;AACA;AACA;;AAEA;AACA;AACA;;AAEA;AACA;AACA,KAAK;;AAEL;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA,KAAK;;AAEL;;AAEA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA,OAAO;;AAEP;AACA;AACA;;AAEA;AACA,KAAK;;AAEL;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA,KAAK;;AAEL;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA,KAAK;;AAEL;AACA;AACA;AACA;AACA;AACA;AACA;AACA,KAAK;AACL;AACA;;AAEA;AACA;AACA;AACA,WAAW,gBAAgB;AAC3B,WAAW,OAAO;AAClB,WAAW,OAAO;AAClB,WAAW,aAAa;AACxB,WAAW,SAAS;AACpB,WAAW,YAAY;AACvB,WAAW,SAAS;AACpB,YAAY;AACZ;;AAEA;;AAEA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA,KAAK;;AAEL;;;AAGA;AACA;AACA;;AAEA;AACA;AACA;;AAEA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;;AAEA;AACA;AACA;;AAEA;AACA;AACA;;AAEA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA,OAAO;;AAEP;AACA;AACA,GAAG;AACH;;AAEA;AACA;AACA;AACA,WAAW,cAAc;AACzB,WAAW,OAAO;AAClB,WAAW,OAAO;AAClB;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;;AAEA;;AAEA;AACA;AACA;;AAEA;AACA;AACA,GAAG;AACH;AACA;;AAEA;AACA;AACA;;AAEA;AACA,oBAAoB,WAAW;AAC/B;;AAEA;AACA;AACA;AACA,OAAO;AACP;AACA;AACA,OAAO;AACP;AACA;AACA;AACA;AACA,SAAS;AACT;AACA;AACA;AACA,KAAK;AACL;;AAEA;;AAEA;AACA;AACA;AACA,GAAG;AACH;;AAEA;AACA;AACA,WAAW,OAAO;AAClB;;AAEA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA,YAAY;AACZ;;AAEA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;;AAEA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA,OAAO;AACP;AACA,GAAG;;AAEH;AACA;;;;;;;;;;;;ACpSA,iBAAiB,mBAAO,EAAE,6DAAa,G;;;;;;;;;;;ACAvC;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,sBAAsB,mBAAO,CAAC,kEAAkB;AAChD;;AAEA;AACA;AACA;AACA,aAAa;AACb;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA,GAAG;;AAEH;AACA;AACA;;AAEA;AACA;AACA;;AAEA;AACA;;AAEA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,OAAO;AACP;AACA;AACA;AACA;AACA,GAAG;;AAEH;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,GAAG;;AAEH;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,GAAG;;AAEH;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;;AAEA;;AAEA;AACA;AACA;AACA;AACA;AACA,OAAO;;AAEP;AACA;AACA;AACA;AACA;AACA;AACA,SAAS;AACT;AACA;AACA,GAAG;;AAEH;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;;AAEA;AACA;;AAEA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;;AAEA;;AAEA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;;AAEA;AACA,GAAG;;AAEH;AACA;;AAEA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA,GAAG;;AAEH;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA,aAAa;AACb;AACA;AACA;AACA;AACA,yCAAyC;AACzC;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;;AAEA;AACA;;AAEA;;AAEA;;AAEA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;;AAEA;AACA;AACA;AACA;AACA;AACA,KAAK;;AAEL;AACA;AACA;;;;;;;;;;;;;;;ACvTA,2DAAiC;AACjC,oDAAoC;AACpC,qDAA6B;AAC7B,+CAAyB;AACzB,iFAA8B;AAE9B,IAAI,IAAI,GAAG,IAAI,CAAC;AAChB,MAAM,IAAI,GAAG,WAAW,CAAC;AAEzB,sCAAsC;AACtC,wEAAwE;AACxE,4BAA4B;AAE5B,SAAgB,QAAQ,CAAC,OAAgC;IACxD,kCAAkC;IAClC,gEAAgE;IAChE,cAAc;IACd,MAAM;IACN,uBAAuB;IAEvB,uDAAuD;IACvD,MAAM,CAAC,QAAQ,CAAC,cAAc,CAAC,YAAY,EAAE,kBAAkB,EAAE,IAAI,CAAC,CAAC;IAEtE,2EAA2E;IAC5E,IAAI,UAAU,GAAG,MAAM,CAAC,QAAQ,CAAC,eAAe,CAAC,uBAAuB,EAAE,GAAG,EAAE;QAE9E,yDAAyD;QACzD,MAAM,OAAO,GAAG,mBAAa,CAAC,MAAM,CAAC,SAAS,CAAC,gBAAgB,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC,CAAC;QAEvF,2FAA2F;QAC3F,EAAE,CAAC,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,OAAO,EAAE,0BAA0B,CAAC,EAAE,CAAC,GAAG,EAAE,EAAE;YACjE,mFAAmF;YACnF,IAAI,GAAG,EAAE;gBACR,MAAM,CAAC,MAAM,CAAC,gBAAgB,CAAC,wEAAwE,OAAO,EAAE,CAAC,CAAC;aAClH;iBAAM;gBACN,6DAA6D;gBAC7D,EAAE,CAAC,MAAM,CAAC;oBACT,OAAO,EAAE,MAAM;oBACf,MAAM,EAAE,IAAI;iBACZ,EAAE,CAAC,GAAG,EAAE,UAAU,EAAE,EAAE;oBACtB,IAAI,GAAG,EAAC;wBACP,MAAM,CAAC,MAAM,CAAC,gBAAgB,CAAC,qDAAqD,GAAG,EAAE,CAAC,CAAC;qBAC3F;yBAAM;wBACN,0FAA0F;wBAC1F,yFAAyF;wBACzF,UAAU,CAAC,OAAO,CAAC,CAAC,OAAO,EAAE,EAAE;4BAE9B,6BAA6B;4BAC7B,EAAE,CAAC,SAAS,CAAC,IAAI,CAAC,IAAI,CAAC,OAAO,EAAE,UAAU,CAAC,EAC3C,uDAAuD,IAAI,CAAC,SAAS,CAAC,OAAO,CAAC,IAAI,EAClF,CAAC,GAAG,EAAE,EAAE,GAAE,OAAO,CAAC,GAAG,CAAC,oDAAoD,GAAG,EAAE,CAAC,GAAC,CAAC,CAAC;4BACnF,MAAM,CAAC,MAAM,CAAC,sBAAsB,CAAC,uCAAuC,CAAC,CAAC;4BAE9E,qEAAqE;4BACrE,IAAG,OAAO,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC,WAAW,CAAC,EAAC;gCAE7C,uEAAuE;gCAEvE,6BAA6B;gCAC7B,EAAE,CAAC,UAAU,CAAC,IAAI,CAAC,IAAI,CAAC,OAAO,EAAE,UAAU,CAAC,EAAE;eACvC,OAAO,CAAC,GAAG,aAAa,OAAO,CAAC,OAAO,gBAAgB,OAAO,CAAC,SAAS,IAAI,EAAE,CAAC,GAAG,EAAE,EAAE,GAAE,OAAO,CAAC,GAAG,CAAC,GAAG,CAAC,GAAC,CAAC,CAAC;gCAElH,0FAA0F;gCAC1F,MAAM,SAAS,GAAG,OAAO,CAAC,SAAS,CAAC;gCACpC,MAAM,QAAQ,GAAG,IAAI,CAAC;gCACtB,MAAM,UAAU,GAAG,SAAS,CAAC,OAAO,CAAC,QAAQ,CAAC,CAAC;gCAC/C,IAAI,UAAU,KAAK,CAAC,CAAC,EAAC;oCACrB,IAAI,GAAG,MAAM,CAAC,OAAO,CAAC,SAAS,CAAC,UAAU,GAAC,CAAC,CAAC,CAAC,CAAC;iCAC/C;qCAAM;oCACN,iFAAiF;oCACjF,wEAAwE;oCACxE,EAAE,CAAC,QAAQ,CAAC,IAAI,CAAC,IAAI,CAAC,OAAO,EAAE,cAAc,CAAC,EAAE,CAAC,GAAG,EAAE,IAAI,EAAE,EAAE;wCAC7D,IAAI,GAAG,EAAC;4CACP,MAAM,CAAC,MAAM,CAAC,gBAAgB,CAAC,sDAAsD,CAAC,CAAC;yCACvF;6CAAM;4CACN,mEAAmE;4CACnE,IAAI,eAAe,GAAG,IAAI,CAAC,QAAQ,EAAE,CAAC;4CAEtC,6BAA6B;4CAC7B,EAAE,CAAC,UAAU,CAAC,IAAI,CAAC,IAAI,CAAC,OAAO,EAAE,UAAU,CAAC,EAAE,yFAAyF,eAAe,IAAI,EAAE,CAAC,GAAG,EAAE,EAAE,GAAE,OAAO,CAAC,GAAG,CAAC,GAAG,CAAC,GAAC,CAAC,CAAC;4CAEzL,8CAA8C;4CAC9C,IAAI,sBAAsB,GAAG,eAAe,CAAC,OAAO,CAAC,iBAAiB,CAAC,GAAC,EAAE,CAAC;4CAE3E,6EAA6E;4CAC7E,IAAI,eAAe,GAAG,eAAe,CAAC,KAAK,CAAC,sBAAsB,EAAE,eAAe,CAAC,OAAO,CAAC,MAAM,CAAC,SAAS,CAAC,QAAQ,EAAE,CAAC,CAAC,CAAC;4CAE1H,6BAA6B;4CAC7B,EAAE,CAAC,UAAU,CAAC,IAAI,CAAC,IAAI,CAAC,OAAO,EAAE,UAAU,CAAC,EAAE,sJAAsJ,eAAe,IAAI,EAAE,CAAC,GAAG,EAAE,EAAE,GAAE,OAAO,CAAC,GAAG,CAAC,GAAG,CAAC,GAAC,CAAC,CAAC;4CAEtP,gEAAgE;4CAChE,oFAAoF;4CACpF,IAAI,sBAAsB,GAAG,eAAe,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;4CACxD,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,sBAAsB,CAAC,MAAM,EAAE,CAAC,EAAE,EAAC;gDACtD,WAAW;gDACX,IAAI,sBAAsB,CAAC,CAAC,CAAC,KAAK,IAAI,EAAC;oDACtC,IAAI,GAAG,MAAM,CAAC,sBAAsB,CAAC,CAAC,GAAC,CAAC,CAAC,CAAC,CAAC;iDAC3C;6CACD;4CAED;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;8CA+BE;yCACF;oCACF,CAAC,CAAC;iCACF;6BACD;wBACF,CAAC,CAAC;qBACF;gBACF,CAAC,CAAC;aACF;QACF,CAAC,CAAC;QAEF,sEAAsE;QACtE,MAAM,KAAK,GAAyB,MAAM,CAAC,MAAM,CAAC,kBAAkB,CACnE,UAAU,EACV,OAAO,EACP,MAAM,CAAC,UAAU,CAAC,GAAG,EACrB;YACC,iBAAiB,EAAE,IAAI;YACvB,aAAa,EAAE,IAAI;YACnB,WAAW,EAAE;gBACZ,EAAE,WAAW,EAAE,IAAI,EAAE,iBAAiB,EAAE,IAAI,EAAC;aAC7C;SACD,CACD,CAAC;QAEF,KAAK,CAAC,OAAO,CAAC,IAAI;YACjB;;;;;;;;2BAQwB,IAAI,IAAI,IAAI;;WAE5B;IACV,CAAC,CAAC;IACF,mBAAmB;IAEnB,OAAO,CAAC,aAAa,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC;AACxC,CAAC;AA/JD,4BA+JC;AAAA,CAAC;AAEF,SAAgB,UAAU;AAC1B,CAAC;AADD,gCACC;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;IAuII;;;;;;;;;;;;ACxTJ,0C;;;;;;;;;;;ACAA,+B;;;;;;;;;;;ACAA,+B;;;;;;;;;;;ACAA,iC;;;;;;;;;;;ACAA,gC;;;;;;;;;;;ACAA,mC","file":"extension.js","sourcesContent":[" \t// The module cache\n \tvar installedModules = {};\n\n \t// The require function\n \tfunction __webpack_require__(moduleId) {\n\n \t\t// Check if module is in cache\n \t\tif(installedModules[moduleId]) {\n \t\t\treturn installedModules[moduleId].exports;\n \t\t}\n \t\t// Create a new module (and put it into the cache)\n \t\tvar module = installedModules[moduleId] = {\n \t\t\ti: moduleId,\n \t\t\tl: false,\n \t\t\texports: {}\n \t\t};\n\n \t\t// Execute the module function\n \t\tmodules[moduleId].call(module.exports, module, module.exports, __webpack_require__);\n\n \t\t// Flag the module as loaded\n \t\tmodule.l = true;\n\n \t\t// Return the exports of the module\n \t\treturn module.exports;\n \t}\n\n\n \t// expose the modules object (__webpack_modules__)\n \t__webpack_require__.m = modules;\n\n \t// expose the module cache\n \t__webpack_require__.c = installedModules;\n\n \t// define getter function for harmony exports\n \t__webpack_require__.d = function(exports, name, getter) {\n \t\tif(!__webpack_require__.o(exports, name)) {\n \t\t\tObject.defineProperty(exports, name, { enumerable: true, get: getter });\n \t\t}\n \t};\n\n \t// define __esModule on exports\n \t__webpack_require__.r = function(exports) {\n \t\tif(typeof Symbol !== 'undefined' && Symbol.toStringTag) {\n \t\t\tObject.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });\n \t\t}\n \t\tObject.defineProperty(exports, '__esModule', { value: true });\n \t};\n\n \t// create a fake namespace object\n \t// mode & 1: value is a module id, require it\n \t// mode & 2: merge all properties of value into the ns\n \t// mode & 4: return value when already ns object\n \t// mode & 8|1: behave like require\n \t__webpack_require__.t = function(value, mode) {\n \t\tif(mode & 1) value = __webpack_require__(value);\n \t\tif(mode & 8) return value;\n \t\tif((mode & 4) && typeof value === 'object' && value && value.__esModule) return value;\n \t\tvar ns = Object.create(null);\n \t\t__webpack_require__.r(ns);\n \t\tObject.defineProperty(ns, 'default', { enumerable: true, value: value });\n \t\tif(mode & 2 && typeof value != 'string') for(var key in value) __webpack_require__.d(ns, key, function(key) { return value[key]; }.bind(null, key));\n \t\treturn ns;\n \t};\n\n \t// getDefaultExport function for compatibility with non-harmony modules\n \t__webpack_require__.n = function(module) {\n \t\tvar getter = module && module.__esModule ?\n \t\t\tfunction getDefault() { return module['default']; } :\n \t\t\tfunction getModuleExports() { return module; };\n \t\t__webpack_require__.d(getter, 'a', getter);\n \t\treturn getter;\n \t};\n\n \t// Object.prototype.hasOwnProperty.call\n \t__webpack_require__.o = function(object, property) { return Object.prototype.hasOwnProperty.call(object, property); };\n\n \t// __webpack_public_path__\n \t__webpack_require__.p = \"\";\n\n\n \t// Load entry module and return exports\n \treturn __webpack_require__(__webpack_require__.s = \"./src/extension.ts\");\n","module.exports = require( './lib/connected-domain' );","/**\n * calculate all the connected domains based on the given two-dimensional array\n */\n\n/**\n * @param {Array} tdArray\n * @param {Function} indicator It receive the raw point data as the first parameter and decide what kind of domain the point belongs to, it should return a string as a domain identifier.\n * @param {Boolean} hardlink If use hard link. Default to false.\n * @return {Object} [{ bounding: { w: 12, h: 19, x: 0, y: 1 }, points: [ { x: 1, y: 2, point: {} } ], identifier: 'blue', domainId: 1 } ]\n */\nmodule.exports = function( tdArray, indicator, hardlink ){\n\n hardlink = hardlink || false;\n\n if( !tdArray ){\n throw new Error( 'tdArray must be provided' );\n }\n\n if( !indicator ){\n throw new Error( 'indicator must be provided' );\n }\n\n // clone 一份数据,因为需要对饮用进行修改,方便执行\n tdArray = JSON.parse( JSON.stringify( tdArray ) );\n\n // Result\n var domains = {};\n var domainUUID = 0;\n var pointsHash = {};\n\n // 遍历数组,划分domain\n\n tdArray.forEach(function( row, y ){\n\n row.forEach(function( colItem, x ){\n\n // get the current point identifier.\n var identifier = indicator( colItem, x, y );\n\n // get neighbours\n // Except for Undefined every data type is valid.\n var neighbours = [];\n\n // top neighbour\n if( tdArray[ y - 1 ] && tdArray[ y - 1 ][ x ] !== undefined ){\n neighbours.push( pointsHash[ x + '_' + ( y - 1 ) ] );\n }\n\n // left neighbour\n if( row[ x - 1 ] !== undefined ){\n neighbours.push( pointsHash[ ( x - 1 ) + '_' + y ] );\n }\n\n // soft link will treat corner link as domain link.\n if( !hardlink ){\n // top left neighbour\n if( tdArray[ y - 1 ] && tdArray[ y - 1 ][ x - 1 ] !== undefined ){\n neighbours.push( pointsHash[ ( x - 1 ) + '_' + ( y - 1 ) ] );\n }\n\n // top right neighbour\n if( tdArray[ y - 1 ] && tdArray[ y - 1 ][ x + 1 ] !== undefined ){\n neighbours.push( pointsHash[ ( x + 1 ) + '_' + ( y - 1 ) ] );\n }\n }\n\n if( neighbours.length ){\n var matched = false;\n\n neighbours.forEach(function( neighbour ){\n\n if( neighbour.identifier == identifier ){\n\n // If the neighbour is the first neighbour has the same identifier\n if( !matched ){\n addPointToDomain( colItem, x, y, neighbour.domainId );\n matched = true;\n }\n\n // If more than one neighbour matched, check if these neighbours belong to the same domain\n // If not, merge these domains since they connects to each other.\n else {\n var colItemPoint = pointsHash[ x + '_' + y ];\n if( neighbour.domainId != colItemPoint.domainId ){\n mergeDomains( neighbour.domainId, colItemPoint.domainId );\n }\n }\n }\n });\n\n if( !matched ){\n addNewDomain( colItem, x, y, identifier );\n }\n }\n else {\n addNewDomain( colItem, x, y, identifier );\n }\n });\n });\n\n // some summary\n var result = {\n domains: [],\n totalDomains: 0,\n groupByIdentifier: {},\n totalIdentifiers: 0\n };\n\n var domainId = null;\n var identifier = null;\n var domain = null;\n for( domainId in domains ){\n domain = domains[ domainId ];\n domain.bounding = calculateBounding( domain.points );\n identifier = domain.identifier;\n\n result.domains.push( domain );\n result.totalDomains++;\n\n if( !( identifier in result.groupByIdentifier ) ){\n result.groupByIdentifier[ identifier ] = [];\n result.totalIdentifiers++;\n }\n\n result.groupByIdentifier[ identifier ].push( domain );\n }\n\n\n function calculateBounding( points ){\n\n var minX = null;\n var minY = null;\n var maxX = null;\n var maxY = null;\n\n points.forEach(function( point ){\n\n if( minX === null || point.x < minX ){\n minX = point.x;\n }\n\n if( minY === null || point.y < minY ){\n minY = point.y;\n }\n\n if( maxX === null || point.x > maxX ){\n maxX = point.x;\n }\n\n if( maxY === null || point.y > maxY ){\n maxY = point.y;\n }\n });\n\n var w = maxX - minX;\n var h = maxY - minY;\n\n return {\n x: minX,\n y: minY,\n w: w,\n h: h\n };\n }\n\n /**\n *\n * @param point\n * @param x\n * @param y\n * @param identifier\n */\n function addNewDomain( point, x, y, identifier ){\n\n var newDomain = {\n identifier: identifier,\n domainId: ++domainUUID,\n bounding: {},\n points: []\n };\n\n var newPoint = {\n value: point,\n x: x,\n y: y,\n identifier: identifier,\n domainId: newDomain.domainId\n };\n\n pointsHash[ x + '_' + y ] = {\n value: point,\n identifier: identifier,\n domainId: newDomain.domainId\n };\n\n newDomain.points.push( newPoint );\n\n domains[ newDomain.domainId ] = newDomain;\n }\n\n /**\n * add a point to a existing domain, and attach properties domainId and identifier to point.\n * @param point\n * @param x\n * @param y\n * @param domainId\n */\n function addPointToDomain( point, x, y, domainId ){\n\n var domain = domains[ domainId ];\n var newPoint = {\n value: point,\n x: x,\n y: y,\n identifier: domain.identifier,\n domainId: domainId\n };\n\n pointsHash[ x + '_' + y ] = {\n value: point,\n identifier: domain.identifier,\n domainId: domainId\n };\n\n domain.points.push( newPoint );\n }\n\n /**\n * 将 domainB 合并到 domainA\n * @param domainAId\n * @param domainBId\n */\n function mergeDomains( domainAId, domainBId ){\n\n var domainA = domains[ domainAId ];\n var domainB = domains[ domainBId ];\n\n if( domainA.identifier == domainB.identifier ){\n // 更新 domainB 的domainId\n\n domainB.domainId = domainA.domainId;\n\n domainB.points.forEach(function( point ){\n point.domainId = domainA.domainId;\n pointsHash[ point.x + '_' + point.y ].domainId = domainA.domainId;\n });\n\n domainA.points = domainA.points.concat( domainB.points );\n\n // 删除domainB\n delete domains[ domainBId ];\n }\n }\n\n return result;\n};","module.exports = require('./lib');\n","var ChildProcess = require('child_process');\nvar IS_WIN = process.platform === 'win32';\nvar TableParser = require('table-parser');\n/**\n * End of line.\n * Basically, the EOL should be:\n * - windows: \\r\\n\n * - *nix: \\n\n * But i'm trying to get every possibilities covered.\n */\nvar EOL = /(\\r\\n)|(\\n\\r)|\\n|\\r/;\nvar SystemEOL = require('os').EOL;\n\n/**\n * Execute child process\n * @type {Function}\n * @param {String[]} args\n * @param {Function} callback\n * @param {Object=null} callback.err\n * @param {Object[]} callback.stdout\n */\n\nvar Exec = module.exports = exports = function (args, callback) {\n var spawn = ChildProcess.spawn;\n\n // on windows, if use ChildProcess.exec(`wmic process get`), the stdout will gives you nothing\n // that's why I use `cmd` instead\n if (IS_WIN) {\n\n var CMD = spawn('cmd');\n var stdout = '';\n var stderr = null;\n\n CMD.stdout.on('data', function (data) {\n stdout += data.toString();\n });\n\n CMD.stderr.on('data', function (data) {\n\n if (stderr === null) {\n stderr = data.toString();\n }\n else {\n stderr += data.toString();\n }\n });\n\n CMD.on('exit', function () {\n\n var beginRow;\n stdout = stdout.split(EOL);\n\n // Find the line index for the titles\n stdout.forEach(function (out, index) {\n if (out && typeof beginRow == 'undefined' && out.indexOf('CommandLine') === 0) {\n beginRow = index;\n }\n });\n\n // get rid of the start (copyright) and the end (current pwd)\n stdout.splice(stdout.length - 1, 1);\n stdout.splice(0, beginRow);\n\n callback(stderr, stdout.join(SystemEOL) || false);\n });\n\n CMD.stdin.write('wmic process get ProcessId,ParentProcessId,CommandLine \\n');\n CMD.stdin.end();\n }\n else {\n if (typeof args === 'string') {\n args = args.split(/\\s+/);\n }\n const child = spawn('ps', args);\n var stdout = '';\n var stderr = null;\n\n child.stdout.on('data', function (data) {\n stdout += data.toString();\n });\n\n child.stderr.on('data', function (data) {\n\n if (stderr === null) {\n stderr = data.toString();\n }\n else {\n stderr += data.toString();\n }\n });\n\n child.on('exit', function () {\n if (stderr) {\n return callback(stderr.toString());\n }\n else {\n callback(null, stdout || false);\n }\n });\n }\n};\n\n/**\n * Query Process: Focus on pid & cmd\n * @param query\n * @param {String|String[]} query.pid\n * @param {String} query.command RegExp String\n * @param {String} query.arguments RegExp String\n * @param {String|array} query.psargs\n * @param {Function} callback\n * @param {Object=null} callback.err\n * @param {Object[]} callback.processList\n * @return {Object}\n */\n\nexports.lookup = function (query, callback) {\n\n /**\n * add 'lx' as default ps arguments, since the default ps output in linux like \"ubuntu\", wont include command arguments\n */\n var exeArgs = query.psargs || ['lx'];\n var filter = {};\n var idList;\n\n // Lookup by PID\n if (query.pid) {\n\n if (Array.isArray(query.pid)) {\n idList = query.pid;\n }\n else {\n idList = [query.pid];\n }\n\n // Cast all PIDs as Strings\n idList = idList.map(function (v) {\n return String(v);\n });\n\n }\n\n\n if (query.command) {\n filter['command'] = new RegExp(query.command, 'i');\n }\n\n if (query.arguments) {\n filter['arguments'] = new RegExp(query.arguments, 'i');\n }\n\n if (query.ppid) {\n filter['ppid'] = new RegExp(query.ppid);\n }\n\n return Exec(exeArgs, function (err, output) {\n if (err) {\n return callback(err);\n }\n else {\n var processList = parseGrid(output);\n var resultList = [];\n\n processList.forEach(function (p) {\n\n var flt;\n var type;\n var result = true;\n\n if (idList && idList.indexOf(String(p.pid)) < 0) {\n return;\n }\n\n for (type in filter) {\n flt = filter[type];\n result = flt.test(p[type]) ? result : false;\n }\n\n if (result) {\n resultList.push(p);\n }\n });\n\n callback(null, resultList);\n }\n });\n};\n\n/**\n * Kill process\n * @param pid\n * @param {Object|String} signal\n * @param {String} signal.signal\n * @param {number} signal.timeout\n * @param next\n */\n\nexports.kill = function( pid, signal, next ){\n //opts are optional\n if(arguments.length == 2 && typeof signal == 'function'){\n next = signal;\n signal = undefined;\n }\n\n var checkTimeoutSeconds = (signal && signal.timeout) || 30;\n\n if (typeof signal === 'object') {\n signal = signal.signal;\n }\n\n try {\n process.kill(pid, signal);\n } catch(e) {\n return next && next(e);\n }\n\n var checkConfident = 0;\n var checkTimeoutTimer = null;\n var checkIsTimeout = false;\n\n function checkKilled(finishCallback) {\n exports.lookup({ pid: pid }, function(err, list) {\n if (checkIsTimeout) return;\n\n if (err) {\n clearTimeout(checkTimeoutTimer);\n finishCallback && finishCallback(err);\n } else if(list.length > 0) {\n checkConfident = (checkConfident - 1) || 0;\n checkKilled(finishCallback);\n } else {\n checkConfident++;\n if (checkConfident === 5) {\n clearTimeout(checkTimeoutTimer);\n finishCallback && finishCallback();\n } else {\n checkKilled(finishCallback);\n }\n }\n });\n }\n\n next && checkKilled(next);\n\n checkTimeoutTimer = next && setTimeout(function() {\n checkIsTimeout = true;\n next(new Error('Kill process timeout'));\n }, checkTimeoutSeconds * 1000);\n};\n\n/**\n * Parse the stdout into readable object.\n * @param {String} output\n */\n\nfunction parseGrid(output) {\n if (!output) {\n return [];\n }\n return formatOutput(TableParser.parse(output));\n}\n\n/**\n * format the structure, extract pid, command, arguments, ppid\n * @param data\n * @return {Array}\n */\n\nfunction formatOutput(data) {\n var formatedData = [];\n data.forEach(function (d) {\n var pid = ( d.PID && d.PID[0] ) || ( d.ProcessId && d.ProcessId[0] ) || undefined;\n var cmd = d.CMD || d.CommandLine || d.COMMAND || undefined;\n var ppid = ( d.PPID && d.PPID[0] ) || ( d.ParentProcessId && d.ParentProcessId[0] ) || undefined;\n\n if (pid && cmd) {\n var command = cmd[0];\n var args = '';\n\n if (cmd.length > 1) {\n args = cmd.slice(1);\n }\n\n formatedData.push({\n pid: pid,\n command: command,\n arguments: args,\n ppid: ppid\n });\n }\n });\n\n return formatedData;\n}\n","module.exports = require( './lib/index' );","/**\n *\n * 1, define the edge ( begin and end ) of every title field\n * 2, parse all the lines except the title line, get all the connected-domains\n * 3, group all the connected-domains vertically overlapped.\n * 4, a domain group belongs to a title field if they vertically overlapped\n * 5, calculate all the edge info through the group domain and title field relations.\n */\nvar ConnectedDomain = require('connected-domain');\nvar EMPTY_EX = /\\s/;\n\n/**\n * The output sting of cmd to parse\n * @param output\n * @returns {Array}\n */\nmodule.exports.parse = function (output) {\n\n // Split into lines\n // Basically, the EOL should be:\n // - windows: \\r\\n\n // - *nix: \\n\n // But i'm trying to get every possibilities covered.\n var linesTmp = output.split(/(\\r\\n)|(\\n\\r)|\\n|\\r/);\n\n // valid lines\n var lines = [];\n // title field info, mapped with filed name.\n var titleInfo = {};\n // the two dimensional array of the lines\n var twoDimArray = [];\n\n // get rid of all the empty lines.\n linesTmp.forEach(function (line) {\n if (line && line.trim()) {\n lines.push(line);\n }\n });\n\n // build title fields edge info\n // build two dimensional array for Connected-Domain to parse.\n lines.forEach(function (line, index) {\n\n // Treat the first line as the title fields line\n if (index == 0) {\n var fields = line.split(/\\s+/);\n\n // record the beginning and ending for each field\n fields.forEach(function (field, idx) {\n\n if (field) {\n var info = titleInfo[field] = {};\n var indexBegin = line.indexOf(field);\n var indexEnd = indexBegin + field.length;\n\n if (idx == 0) {\n info.titleBegin = 0;\n }\n else {\n info.titleBegin = indexBegin;\n }\n\n if (idx == fields.length - 1) {\n info.titleEnd = line.length - 1;\n }\n else {\n info.titleEnd = indexEnd;\n }\n }\n });\n }\n else {\n twoDimArray[index - 1] = line.split('');\n }\n });\n\n // In the connected-domain aspect of view, all the blanks are connected, and all the non-blanks are connected.\n var connectedDomains = ConnectedDomain(twoDimArray, function (value) {\n if (EMPTY_EX.test(value)) {\n return -1;\n }\n else {\n return 1;\n }\n }, true);\n\n // all the connected domains grouped if they are vertically overlapped.\n var valuesDomainsVerticalGroups = [];\n\n // sore the domain list make 'x' in ascending order, it will prevent the situation that:\n // 1, two domains are not overlapped, so two groups are created for them at first\n // 2, another domain is found overlapped with both of the domains at the first step.\n // 3, In this situation the three groups have to be merged, which is complicated to implement.\n //\n // If the list is sorted in this order, this situation can't happen, because:\n // - 1, If two non-overlapped domains A, B ( the \"x\" value of A less than B ) are found first.\n // - 2, Since the list is in 'x' ascending order, the 'x' values of the following domains must larger or equal to the \"x\" of B, which means they will never overlapped with domain A.\n // - 3, So this situation can't happen.\n connectedDomains.domains.sort(function (a, b) {\n return a.bounding.x - b.bounding.x;\n });\n\n // Group domains vertically overlapped.\n connectedDomains.domains.forEach(function (domain) {\n // only handle un-empty domain\n if (domain.identifier === 1) {\n var overlapped = false;\n\n // If overlapped\n valuesDomainsVerticalGroups.forEach(function (group) {\n var bounding = domain.bounding;\n var left = bounding.x;\n var right = bounding.x + bounding.w;\n\n if (overlap(left, right, group.begin, group.end)) {\n\n overlapped = true;\n group.domains.push(domain);\n group.begin = group.begin > left ? left : group.begin;\n group.end = group.end < right ? right : group.end;\n }\n });\n\n // If not overlapped with any group, then create a new group\n if (!overlapped) {\n valuesDomainsVerticalGroups.push({\n begin: domain.bounding.x,\n end: domain.bounding.x + domain.bounding.w,\n domains: [domain]\n });\n }\n }\n });\n\n // connect all the groups to the title fields\n valuesDomainsVerticalGroups.forEach(function (group) {\n var title = null;\n var info = null;\n var overlapped = false;\n\n var minimunLeftDistance = null;\n var nearestLeftTitle = null;\n var distance = null;\n\n for (title in titleInfo) {\n info = titleInfo[title];\n\n /**\n * The calculation below is to find the nearest left title field to the group, in case no overlapped title field found.\n */\n if (group.begin > info.titleBegin) {\n distance = group.begin - info.titleBegin;\n\n if (!nearestLeftTitle || ( distance < minimunLeftDistance )) {\n nearestLeftTitle = title;\n minimunLeftDistance = distance;\n }\n }\n\n if (overlap(group.begin, group.end, info.titleBegin, info.titleEnd)) {\n\n overlapped = true;\n info.titleBegin = info.titleBegin > group.begin ? group.begin : info.titleBegin;\n info.titleEnd = info.titleEnd < group.end ? group.end : info.titleEnd;\n }\n }\n\n // Groups not match any title field belongs to the nearest left title field\n if (!overlapped && nearestLeftTitle) {\n var nearestTitleField = titleInfo[nearestLeftTitle];\n nearestTitleField.titleBegin = nearestTitleField.titleBegin > group.begin ? group.begin : nearestTitleField.titleBegin;\n nearestTitleField.titleEnd = nearestTitleField.titleEnd < group.end ? group.end : nearestTitleField.titleEnd;\n\n }\n });\n\n // The final result\n var result = [];\n\n // Since we have got all the title bounding edges, we can split all the lines into values now\n lines.forEach(function (line, index) {\n // skip the first line\n if (index > 0) {\n\n var lineItem = {};\n var title = null;\n var info = null;\n var value = null;\n for (title in titleInfo) {\n info = titleInfo[title];\n value = line.substring(info.titleBegin, info.titleEnd + 1);\n lineItem[title] = splitValue(value.trim());\n }\n\n result.push(lineItem);\n }\n });\n\n return result;\n};\n\n/**\n * Test if two bounding overlapped vertically\n * @param begin1\n * @param end1\n * @param begin2\n * @param end2\n * @returns {boolean}\n */\nfunction overlap(begin1, end1, begin2, end2) {\n return ( begin1 > begin2 && begin1 < end2 ) || // 2--1--2--1 or 2--1--1--2\n ( end1 > begin2 && end1 < end2 ) || // 1--2--1--2 or 2--1--1--2\n ( begin1 <= begin2 && end1 >= end2 );// 21--12 or 1--2--2--1\n}\n\n/**\n * transform a string value into array. It's not just split(), but also to consider some chunk that wrapped with `\"`, like below:\n * \"C:\\Program Files\\Google\\Chrome\\Application\\chrome.exe\" --type=renderer --lang=zh-CN, `C:\\Program Files\\Google\\Chrome\\Application\\chrome.exe` should be treated as a whole,\n * also, be careful don't be mislead by format like `--name=\"neekey\"`, even more complicated: `--name=\"Neekey Ni\"`\n * so, `\"C:\\Program Files\\Internet Explorer\\iexplore.exe\" --name=\"Jack Neekey\"` should split into:\n * - C:\\Program Files\\Internet Explorer\\iexplore.exe // without `\"`\n * - --name=\"Jack Neekey\" // with `\"`\n */\nfunction splitValue(value) {\n\n var match = value.match(/\"/g);\n\n // If only one \" found, then just ignore it\n if (!match || match.length == 1) {\n return value.split(/\\s+/);\n }\n else {\n var result = [];\n var chunk = null;\n var ifInWrappedChunk = false;\n var ifInPureWrappedChunk = false;\n var quotaCount = 0;\n\n // If the match length is a even, than nothing special, if a odd, ignore the last one.\n var maxQuotaCount = match.length % 2 == 0 ? match.length : match.length - 1;\n\n var previousItem = null;\n var values = value.split('');\n\n values.forEach(function (item, index) {\n\n if (item !== ' ') {\n\n if (item === '\"') {\n // quota chunk begin\n if (ifInWrappedChunk === false && quotaCount <= maxQuotaCount) {\n ifInWrappedChunk = true;\n quotaCount++;\n\n // pure quota chunk begin\n if (previousItem === ' ' || previousItem === null) {\n ifInPureWrappedChunk = true;\n chunk = '';\n }\n // normal continue\n else {\n chunk += item;\n }\n }\n // quota chunk end\n else if (ifInWrappedChunk === true) {\n ifInWrappedChunk = false;\n quotaCount++;\n\n // pure quota chunk end\n if (ifInPureWrappedChunk === true) {\n ifInPureWrappedChunk = false;\n result.push(chunk);\n chunk = null;\n }\n // normal continue\n else {\n chunk += item;\n }\n }\n }\n // normal begin\n else if (ifInWrappedChunk === false && ( previousItem === ' ' || previousItem === null )) {\n chunk = item;\n }\n // normal or quota chunk continue.\n else {\n chunk += item;\n }\n }\n // quota chunk continue, in quota chunk, blank is valid.\n else if (ifInWrappedChunk) {\n chunk += item;\n }\n // if not in quota chunk, them a blank means an end. But make sure chunk is exist, cause that could be blanks at the beginning.\n else if (chunk !== null) {\n result.push(chunk);\n chunk = null;\n }\n\n previousItem = item;\n\n // If this is the last one, but chunk is not end\n if (index == ( values.length - 1 ) && chunk !== null) {\n result.push(chunk);\n chunk = null;\n }\n });\n\n return result;\n }\n}\n","import * as vscode from 'vscode';\nimport { fileURLToPath } from 'url';\nimport * as path from 'path';\nimport * as fs from 'fs';\nimport * as ps from 'ps-node';\n\nlet PORT = 6006;\nconst host = 'localhost';\n\n// import * as express from 'express';\n// import { resolveCliPathFromVSCodeExecutablePath } from 'vscode-test';\n// const server = express();\n\nexport function activate(context: vscode.ExtensionContext) {\n\t// server.get('/', (req, res) => {\n\t// \tvscode.window.showInformationMessage('Aesop server online');\n\t// \tres.end();\n\t// });\n\t// server.listen(PORT);\n\n\t//set the extension context equal to \"aesop is running\"\n\tvscode.commands.executeCommand(\"setContext\", \"is-running-aesop\", true);\n\n //create disposable variable type, registers awaken command & opens webview\n\tlet disposable = vscode.commands.registerCommand('extension.aesopAwaken', () => {\n\n\t\t//define a path to the root working directory of the user\n\t\tconst rootDir = fileURLToPath(vscode.workspace.workspaceFolders[0].uri.toString(true));\n\n\t\t//check first to ensure that Storybook has been depended into the current working directory\n\t\tfs.access(path.join(rootDir, '/node_modules/@storybook'), (err) => {\n\t\t\t//if the filepath isn't found, show the user what Aesop is reading as the root path\n\t\t\tif (err) {\n\t\t\t\tvscode.window.showErrorMessage(`Aesop could not find Storybook as a dependency in the active folder, ${rootDir}`);\n\t\t\t}\telse {\n\t\t\t\t//check to see if a storybook node process is already running\n\t\t\t\tps.lookup({\n\t\t\t\t\tcommand: 'node',\n\t\t\t\t\tpsargs: 'ux'\n\t\t\t\t}, (err, resultList) => {\n\t\t\t\t\tif (err){\n\t\t\t\t\t\tvscode.window.showErrorMessage(`Failed looking for running Node processes. Error: ${err}`);\n\t\t\t\t\t} else {\n\t\t\t\t\t\t//if the process lookup was able to find running processes, iterate through to review them\n\t\t\t\t\t\t//potential problem: we may also need to account for running processes given no port flag\n\t\t\t\t\t\tresultList.forEach((process) => {\n\n\t\t\t\t\t\t\t// ---> OUTPUT LOGGER <--- //\n\t\t\t\t\t\t\tfs.writeFile(path.join(rootDir, 'YOLO.txt'),\n\t\t\t\t\t\t\t`Here is the JSON-stringified version of a process:\\n${JSON.stringify(process)}\\n`,\n\t\t\t\t\t\t\t(err) => {console.log(`Couldn't output process information to YOLO.txt: ${err}`)});\n\t\t\t\t\t\t\tvscode.window.showInformationMessage('Check YOLO.txt for output information');\n\n\t\t\t\t\t\t\t//check if any running processes are using the start-storybook script\n\t\t\t\t\t\t\tif(process.arguments[0].includes('storybook')){\n\n\t\t\t\t\t\t\t\t//stretch goal: check for multiple instances of storybook and reconcile\n\n\t\t\t\t\t\t\t\t// ---> OUTPUT LOGGER <--- //\n\t\t\t\t\t\t\t\tfs.appendFile(path.join(rootDir, 'YOLO.txt'), `This process matches for 'storybook'search string:\\n\n\t\t\t\t\t\t\t\tPID: ${process.pid}, COMMAND:${process.command}, ARGUMENTS: ${process.arguments}\\n`, (err) => {console.log(err)});\n\n\t\t\t\t\t\t\t\t//if so, extract port number and use that value to populate the webview with that contents\n\t\t\t\t\t\t\t\tconst sbProcess = process.arguments;\n\t\t\t\t\t\t\t\tconst portFlag = '-p';\n\t\t\t\t\t\t\t\tconst pFlagIndex = sbProcess.indexOf(portFlag);\n\t\t\t\t\t\t\t\tif (pFlagIndex !== -1){\n\t\t\t\t\t\t\t\t\tPORT = Number(process.arguments[pFlagIndex+1]);\n\t\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\t\t//if no processes match 'storybook', we will have to spin up the storybook server\n\t\t\t\t\t\t\t\t\t//starts by extracting the existing storybook script in the package.json\n\t\t\t\t\t\t\t\t\tfs.readFile(path.join(rootDir, 'package.json'), (err, data) => {\n\t\t\t\t\t\t\t\t\t\tif (err){\n\t\t\t\t\t\t\t\t\t\t\tvscode.window.showErrorMessage(`Does this root folder contain a \"package.json\" file?`);\n\t\t\t\t\t\t\t\t\t\t}\telse {\n\t\t\t\t\t\t\t\t\t\t\t//enter the package.JSON file and retrieve its contents as a string\n\t\t\t\t\t\t\t\t\t\t\tlet packageJSONText = data.toString();\n\n\t\t\t\t\t\t\t\t\t\t\t// ---> OUTPUT LOGGER <--- //\n\t\t\t\t\t\t\t\t\t\t\tfs.appendFile(path.join(rootDir, 'YOLO.txt'), `Here is the full contents of the package.json file from the user's workspace folder:\\n${packageJSONText}\\n`, (err) => {console.log(err)});\n\n\t\t\t\t\t\t\t\t\t\t\t//find where the \"storybook\" script is defined\n\t\t\t\t\t\t\t\t\t\t\tlet targetScriptStartIndex = packageJSONText.indexOf(`\\\"storybook\\\"\\:`)+12;\n\n\t\t\t\t\t\t\t\t\t\t\t//retrieve the value (i.e. the entire line of text) of the \"storybook\" script\n\t\t\t\t\t\t\t\t\t\t\tlet retrievedScript = packageJSONText.slice(targetScriptStartIndex, packageJSONText.indexOf(vscode.EndOfLine.toString()));\n\n\t\t\t\t\t\t\t\t\t\t\t// ---> OUTPUT LOGGER <--- //\n\t\t\t\t\t\t\t\t\t\t\tfs.appendFile(path.join(rootDir, 'YOLO.txt'), `This is what our readFile function (line 72) returns when it attempts to retrieve (line 82) the \"storybook\" script from your app's package.json:\\n${retrievedScript}\\n`, (err) => {console.log(err)});\n\n\t\t\t\t\t\t\t\t\t\t\t//iterate through that text string and parse out important flags\n\t\t\t\t\t\t\t\t\t\t\t//it is more helpful to split it into an array separated by whitespace to grab these\n\t\t\t\t\t\t\t\t\t\t\tlet retrievedScriptAsArray = retrievedScript.split(' ');\n\t\t\t\t\t\t\t\t\t\t\tfor (let i = 0; i < retrievedScriptAsArray.length; i++){\n\t\t\t\t\t\t\t\t\t\t\t\t//add flags\n\t\t\t\t\t\t\t\t\t\t\t\tif (retrievedScriptAsArray[i] === '-p'){\n\t\t\t\t\t\t\t\t\t\t\t\t\tPORT = Number(retrievedScriptAsArray[i+1]);\n\t\t\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\t\t\t\t\t/*\n\t\t\t\t\t\t\t\t\t\t\tvscode.tasks.registerTaskProvider('runStorybook', {\n\t\t\t\t\t\t\t\t\t\t\t\tprovideTasks(token?: vscode.CancellationToken) {\n\t\t\t\t\t\t\t\t\t\t\t\t\t\treturn [\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tnew vscode.Task({type: 'runStorybook'}, vscode.TaskScope.Workspace,\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\"Aesop Chronicle\", \"aesop\", new vscode.ShellExecution(`npm run storybook --ci`))\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t];\n\t\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\tresolveTask(task: vscode.Task, token?: vscode.CancellationToken) {\n\t\t\t\t\t\t\t\t\t\t\t\t\t\treturn task;\n\t\t\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t\t\t});\n\n\t\t\t\t\t\t\t\t\t\t\t//define the script text to execute to the virtual terminal instance\n\t\t\t\t\t\t\t\t\t\t\tconst bootScript = `storybook --ci`;\n\t\t\t\t\t\t\t\t\t\t\tconst bootStorybook = new vscode.ProcessExecution(bootScript, {cwd: rootDir});\n\n\t\t\t\t\t\t\t\t\t\t\t//now create a virtual terminal and execute our special npm script for it\n\t\t\t\t\t\t\t\t\t\t\t//this first requires creating an eventEmitter that will fire that script\n\t\t\t\t\t\t\t\t\t\t\tconst scriptEmitter = new vscode.EventEmitter();\n\t\t\t\t\t\t\t\n\t\t\t\t\t\t\t\t\t\t\t//we also define a slave process Pseudoterminal (allowing Aesop to control the terminal)\n\t\t\t\t\t\t\t\t\t\t\tconst pty: vscode.Pseudoterminal = {\n\t\t\t\t\t\t\t\t\t\t\t\tonDidWrite: scriptEmitter.event,\n\t\t\t\t\t\t\t\t\t\t\t\topen: () =>\tscriptEmitter.fire(bootScript),\n\t\t\t\t\t\t\t\t\t\t\t\tclose: () => {},\n\t\t\t\t\t\t\t\t\t\t\t\thandleInput: data => new vscode.ShellExecution(data)\n\t\t\t\t\t\t\t\t\t\t\t};\n\n\t\t\t\t\t\t\t\t\t\t\t//should this just be an active terminal/shellExecution?\n\t\t\t\t\t\t\t\t\t\t\tconst virtualTerminal = vscode.window.createTerminal({name: 'sb-runner', pty});\n\t\t\t\t\t\t\t\t\t\t\t*/\n\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t})\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t})\n\t\t\t\t\t}\n\t\t\t\t})\n\t\t\t}\n\t\t})\n\n\t\t//still inside our disposable variable, let's create the webview panel\n\t\tconst panel : vscode.WebviewPanel = vscode.window.createWebviewPanel(\n\t\t\t'aesop-sb',\n\t\t\t'Aesop',\n\t\t\tvscode.ViewColumn.Two,\n\t\t\t{\n\t\t\t\tenableCommandUris: true,\n\t\t\t\tenableScripts: true,\n\t\t\t\tportMapping: [\n\t\t\t\t\t{ webviewPort: PORT, extensionHostPort: PORT}\n\t\t\t\t]\n\t\t\t}\n\t\t);\n\n\t\tpanel.webview.html =\n\t\t\t`\n\t\t\t\n\t\t\t\t\n\t\t\t\t\t\n\t\t\t\t\t\n\t\t\t\t\tAesop\n\t\t\t\t\n\t\t\t\t\n\t\t\t\t\t\n\t\t\t\t\n\t\t\t`\n\t})\n\t//closes disposable\n\n\tcontext.subscriptions.push(disposable);\n};\n\nexport function deactivate() {\n}\n\n/*\nto-do:\n\tfigure out how to iteratively call sb scripts within our webview\n\twebview messages / scripts to reload\n\tfigure out how to use a tsx rule in webpack to execute scripts\n\tsignal babel to interpret this block as tsx, e.g. something like: //@tsx babel//\n\n//THIS WORKS, but we have no access to the DOM inside our webview//\n\t//now let's read SB's outputted index.html file, and parse out what we need\n\t\tfs.readFile(path.join(rootDir, '/node_modules/@storybook/core/dist/public/index.html'), (err, data) => {\n\t\t\tif (err) console.error(err);\n\t\t\telse {\n\t\t\t\tlet pulledHTML = data.toString();\n\t\t\t\tlet targetPoint = pulledHTML.indexOf('');\n\t\t\t\tlet firstHalf = pulledHTML.slice(0, targetPoint);\n\t\t\t\tlet secondHalf = pulledHTML.slice(targetPoint);\n\t\t\t\tpulledHTML = firstHalf.concat(payloadScript).concat(secondHalf);\n\t\t\t\tfs.writeFile(path.join(rootDir, '/node_modules/@storybook/core/dist/public/index.html'), pulledHTML, (err) => {\n\t\t\t\t\tif (err) console.error(err);\n\t\t\t\t\telse {\n\t\t\t\t\t\tvscode.window.showInformationMessage('Successfully injected script');\n\t\t\t\t\t};\n\t\t\t\t});\n\t\t\t}\n\t\t});\n\n\t//declare an empty array (of strings) to push our scripts to during the next part\n\t\tconst scriptArray : Array = [];\n\t\t//define a path to the root working directory of the user\n\t\tconst rootDir = fileURLToPath(vscode.workspace.workspaceFolders[0].uri.toString(true));\n\t\t//now let's read SB's outputted index.html file, and parse out what we need\n\t\tfs.readFile(path.join(rootDir, '/node_modules/@storybook/core/dist/public/index.html'), (err, data) => {\n\t\t\tif (err) console.error(err);\n\t\t\telse {\n\t\t\t\t//if we've read the HTML file, take its contents and stringify it\n\t\t\t\tlet outputFile = data.toString();\n\t\t\t\t// this log shows what our eventual permutations would look like as we carve out the scripts\n\t\t\t\t// vscode.window.showWarningMessage(`what's in it: ${outputFile.slice(outputFile.indexOf('')+6, outputFile.indexOf(''))} \\n`)\n\t\t\t\t//split out the body section of the retrieved html file\n\t\t\t\toutputFile = outputFile.slice(outputFile.indexOf('')+6, outputFile.indexOf(''));\n\t\t\t\tvscode.window.showWarningMessage(`${outputFile} \\n`)\n\n\t\t\t\t//this loop will peel out all the scripts so long as there are any to rip out\n\t\t\t\twhile (outputFile.includes(`\" tags behind\n\t\t\t\t\tlet temp = outputFile.slice(outputFile.indexOf(``));\n\t\t\t\t\tscriptArray.push(temp);\n\t\t\t\t\toutputFile = outputFile.slice(outputFile.indexOf(`\">`)+10);\n\t\t\t\t}\n\t\t\t};\n\t\t});\n\n
\n
\t\n\t
\n\t\n\t\n\t\n
\n\n\tdisposable = vscode.commands.registerCommand('extension.getStories', () => {\n\t\tbuild a command that retrieves Storybook files on startup\n\t\tcan be executed later if Storybook server is spun up after the extension opens\n\t\t\n\t\talso register this command at startup to crawl the file path\n\t\t${vscode.commands.executeCommand('extension.getStories')}\n\t\tvscode.window.showInformationMessage('Aesop is reading from your Storybook.');\n\n\t\tdefine a path to SB webpack bundle outputs (in user workspace /node_modules/ folder)\n\t\tif (vscode.workspace.workspaceFolders[0] !== undefined){\n\t\t\tconst distGlob = new vscode.RelativePattern(vscode.workspace.workspaceFolders[0], \"**(remove)/node_modules/@storybook/core/dist/public\");\n\t\t\t//instantiate a watcher to listen for fs path changes (e.g. file creation/update)\n\t\t\t//bools = options for ignoreCreateEvents?, ignoreChangeEvents?, ignoreDeleteEvents?\t\n\t\t\tconst observer = vscode.workspace.createFileSystemWatcher(distGlob, false, false, false);\n\t\t\t// observer.onDidChange = //resolve//;\t\t// observer.onDidCreate = //resolve//;\n\t\t\t//extract index.html file that outputs into SB's preview pane\n\t\t\tconst htmlGlob = new vscode.RelativePattern(vscode.workspace.workspaceFolders[0], \"*(remove)/node_modules/@storybook/core/dist/public/*.html\");\n\t\t\t//extract necessary bundle scripts to leverage in-app dependencies\n\t\t\tconst scriptGlob = new vscode.RelativePattern(vscode.workspace.workspaceFolders[0], \"*(remove)/node_modules/@storybook/core/dist/public/*.js\");\n\n\t\t\tconsole.log(vscode.Uri.file(fileURLToPath(`/node_modules/@storybook/core/dist/public`)));\n\n\t\t\t//do we need to resolve the Storybook UI script from the /dll/ folder?\n\t\t\t//if extract methods above fail, determine logic to parse out HTML/.js scripts (index 0?);\n\t\t\t//retrieve files with findFiles/relativeFilePath\n\t\t\tconst arrayOfScripts = vscode.workspace.findFiles(distGlob, null, 100);\n\t\t\t//dev check: have we successfully pulled down script files?\n\t\t\t//if so, should we then store them locally, or is there no point?\n\t\t\tif (arrayOfScripts !== undefined){\n\t\t\t\tvscode.window.showInformationMessage(\"Hey, dog: \" + `${arrayOfScripts}`);\n\t\t\t}\n\n\t\t\tvscode.window.showInformationMessage(`\n\t\t\trootPath: ${vscode.workspace.workspaceFolders[0]},\n\t\t\tvscode.Uri: ${vscode.Uri},\n\t\t\tworkspace: ${vscode.workspace},\n\t\t\tdistGlob: ${distGlob.toString()},\n\t\t\thtmlGlob: ${htmlGlob.toString()},\n\t\t\tscriptGlob: ${scriptGlob.toString()}\n\t\t\t`);\n\t\t};\n\n\t\tvscode.window.showInformationMessage(`\n\t\t\trootPath: ${vscode.workspace.workspaceFolders[0].uri.toString()},\\n\n\t\t\tvscode URI parseTest: ${vscode.Uri.parse('file://'+ '/node_modules/@storybook/core/dist/public/index.html')},\\n\n\t\t\tvscode URI parsed w escape: ${vscode.Uri.parse('file://'+ '/node_modules/\\@storybook/core/dist/public/index.html')},\\n\n\t\t\tvscode URI file Test: ${vscode.Uri.file('node_modules/@storybook/core/dist/public/index.html')}\n\t\t\t`);\n\t\t\t\n\t\tconsole.log(`\n\t\trootPath: ${vscode.workspace.workspaceFolders[0]},\n\t\tvscode.Uri: ${vscode.Uri},\n\t\tworkspace: ${vscode.workspace},\n\t\tfileSys: ${vscode.Uri.file(path.join('/'))}`);\n });\n */","module.exports = require(\"child_process\");","module.exports = require(\"fs\");","module.exports = require(\"os\");","module.exports = require(\"path\");","module.exports = require(\"url\");","module.exports = require(\"vscode\");"],"sourceRoot":""} \ No newline at end of file +{"version":3,"sources":["../webpack/bootstrap",".././node_modules/connected-domain/index.js",".././node_modules/connected-domain/lib/connected-domain.js",".././node_modules/ps-node/index.js",".././node_modules/ps-node/lib/index.js",".././node_modules/table-parser/index.js",".././node_modules/table-parser/lib/index.js",".././src/extension.ts","../external \"child_process\"","../external \"fs\"","../external \"os\"","../external \"path\"","../external \"url\"","../external \"vscode\""],"names":[],"mappings":";;QAAA;QACA;;QAEA;QACA;;QAEA;QACA;QACA;QACA;QACA;QACA;QACA;QACA;QACA;QACA;;QAEA;QACA;;QAEA;QACA;;QAEA;QACA;QACA;;;QAGA;QACA;;QAEA;QACA;;QAEA;QACA;QACA;QACA,0CAA0C,gCAAgC;QAC1E;QACA;;QAEA;QACA;QACA;QACA,wDAAwD,kBAAkB;QAC1E;QACA,iDAAiD,cAAc;QAC/D;;QAEA;QACA;QACA;QACA;QACA;QACA;QACA;QACA;QACA;QACA;QACA;QACA,yCAAyC,iCAAiC;QAC1E,gHAAgH,mBAAmB,EAAE;QACrI;QACA;;QAEA;QACA;QACA;QACA,2BAA2B,0BAA0B,EAAE;QACvD,iCAAiC,eAAe;QAChD;QACA;QACA;;QAEA;QACA,sDAAsD,+DAA+D;;QAErH;QACA;;;QAGA;QACA;;;;;;;;;;;;AClFA,iBAAiB,mBAAO,EAAE,uFAAwB,G;;;;;;;;;;;ACAlD;AACA;AACA;;AAEA;AACA,WAAW,MAAM;AACjB,WAAW,SAAS;AACpB,WAAW,QAAQ;AACnB,YAAY,OAAO,GAAG,YAAY,2BAA2B,aAAa,sBAAsB,EAAE,qCAAqC;AACvI;AACA;;AAEA;;AAEA;AACA;AACA;;AAEA;AACA;AACA;;AAEA;AACA;;AAEA;AACA;AACA;AACA;;AAEA;;AAEA;;AAEA;;AAEA;AACA;;AAEA;AACA;AACA;;AAEA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;;AAEA;AACA;;AAEA;;AAEA;;AAEA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,iBAAiB;;AAEjB;AACA;AACA;AACA;AACA;AACA;AACA;AACA,SAAS;AACT,KAAK;;AAEL;AACA;AACA;AACA;AACA,6BAA6B;AAC7B;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;;AAEA;AACA;AACA;AACA;;AAEA;AACA;;;AAGA;;AAEA;AACA;AACA;AACA;;AAEA;;AAEA;AACA;AACA;;AAEA;AACA;AACA;;AAEA;AACA;AACA;;AAEA;AACA;AACA;AACA,SAAS;;AAET;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA,wBAAwB;AACxB;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;;AAEA;;AAEA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;;AAEA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;;AAEA;AACA;;AAEA;;AAEA;AACA;AACA;AACA,aAAa;;AAEb;;AAEA;AACA;AACA;AACA;;AAEA;AACA,E;;;;;;;;;;;AC/PA,iBAAiB,mBAAO,CAAC,kDAAO;;;;;;;;;;;;ACAhC,mBAAmB,mBAAO,CAAC,oCAAe;AAC1C;AACA,kBAAkB,mBAAO,CAAC,0DAAc;AACxC;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,gBAAgB,mBAAO,CAAC,cAAI;;AAE5B;AACA;AACA,UAAU;AACV,WAAW,SAAS;AACpB,WAAW,SAAS;AACpB,WAAW,YAAY;AACvB,WAAW,SAAS;AACpB;;AAEA;AACA;;AAEA;AACA;AACA;;AAEA;AACA;AACA;;AAEA;AACA;AACA,KAAK;;AAEL;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA,KAAK;;AAEL;;AAEA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA,OAAO;;AAEP;AACA;AACA;;AAEA;AACA,KAAK;;AAEL;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA,KAAK;;AAEL;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA,KAAK;;AAEL;AACA;AACA;AACA;AACA;AACA;AACA;AACA,KAAK;AACL;AACA;;AAEA;AACA;AACA;AACA,WAAW,gBAAgB;AAC3B,WAAW,OAAO;AAClB,WAAW,OAAO;AAClB,WAAW,aAAa;AACxB,WAAW,SAAS;AACpB,WAAW,YAAY;AACvB,WAAW,SAAS;AACpB,YAAY;AACZ;;AAEA;;AAEA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA,KAAK;;AAEL;;;AAGA;AACA;AACA;;AAEA;AACA;AACA;;AAEA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;;AAEA;AACA;AACA;;AAEA;AACA;AACA;;AAEA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA,OAAO;;AAEP;AACA;AACA,GAAG;AACH;;AAEA;AACA;AACA;AACA,WAAW,cAAc;AACzB,WAAW,OAAO;AAClB,WAAW,OAAO;AAClB;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;;AAEA;;AAEA;AACA;AACA;;AAEA;AACA;AACA,GAAG;AACH;AACA;;AAEA;AACA;AACA;;AAEA;AACA,oBAAoB,WAAW;AAC/B;;AAEA;AACA;AACA;AACA,OAAO;AACP;AACA;AACA,OAAO;AACP;AACA;AACA;AACA;AACA,SAAS;AACT;AACA;AACA;AACA,KAAK;AACL;;AAEA;;AAEA;AACA;AACA;AACA,GAAG;AACH;;AAEA;AACA;AACA,WAAW,OAAO;AAClB;;AAEA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA,YAAY;AACZ;;AAEA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;;AAEA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA,OAAO;AACP;AACA,GAAG;;AAEH;AACA;;;;;;;;;;;;ACpSA,iBAAiB,mBAAO,EAAE,6DAAa,G;;;;;;;;;;;ACAvC;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,sBAAsB,mBAAO,CAAC,kEAAkB;AAChD;;AAEA;AACA;AACA;AACA,aAAa;AACb;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA,GAAG;;AAEH;AACA;AACA;;AAEA;AACA;AACA;;AAEA;AACA;;AAEA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,OAAO;AACP;AACA;AACA;AACA;AACA,GAAG;;AAEH;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,GAAG;;AAEH;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,GAAG;;AAEH;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;;AAEA;;AAEA;AACA;AACA;AACA;AACA;AACA,OAAO;;AAEP;AACA;AACA;AACA;AACA;AACA;AACA,SAAS;AACT;AACA;AACA,GAAG;;AAEH;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;;AAEA;AACA;;AAEA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;;AAEA;;AAEA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;;AAEA;AACA,GAAG;;AAEH;AACA;;AAEA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA,GAAG;;AAEH;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA,aAAa;AACb;AACA;AACA;AACA;AACA,yCAAyC;AACzC;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;;AAEA;AACA;;AAEA;;AAEA;;AAEA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;A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","file":"extension.js","sourcesContent":[" \t// The module cache\n \tvar installedModules = {};\n\n \t// The require function\n \tfunction __webpack_require__(moduleId) {\n\n \t\t// Check if module is in cache\n \t\tif(installedModules[moduleId]) {\n \t\t\treturn installedModules[moduleId].exports;\n \t\t}\n \t\t// Create a new module (and put it into the cache)\n \t\tvar module = installedModules[moduleId] = {\n \t\t\ti: moduleId,\n \t\t\tl: false,\n \t\t\texports: {}\n \t\t};\n\n \t\t// Execute the module function\n \t\tmodules[moduleId].call(module.exports, module, module.exports, __webpack_require__);\n\n \t\t// Flag the module as loaded\n \t\tmodule.l = true;\n\n \t\t// Return the exports of the module\n \t\treturn module.exports;\n \t}\n\n\n \t// expose the modules object (__webpack_modules__)\n \t__webpack_require__.m = modules;\n\n \t// expose the module cache\n \t__webpack_require__.c = installedModules;\n\n \t// define getter function for harmony exports\n \t__webpack_require__.d = function(exports, name, getter) {\n \t\tif(!__webpack_require__.o(exports, name)) {\n \t\t\tObject.defineProperty(exports, name, { enumerable: true, get: getter });\n \t\t}\n \t};\n\n \t// define __esModule on exports\n \t__webpack_require__.r = function(exports) {\n \t\tif(typeof Symbol !== 'undefined' && Symbol.toStringTag) {\n \t\t\tObject.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });\n \t\t}\n \t\tObject.defineProperty(exports, '__esModule', { value: true });\n \t};\n\n \t// create a fake namespace object\n \t// mode & 1: value is a module id, require it\n \t// mode & 2: merge all properties of value into the ns\n \t// mode & 4: return value when already ns object\n \t// mode & 8|1: behave like require\n \t__webpack_require__.t = function(value, mode) {\n \t\tif(mode & 1) value = __webpack_require__(value);\n \t\tif(mode & 8) return value;\n \t\tif((mode & 4) && typeof value === 'object' && value && value.__esModule) return value;\n \t\tvar ns = Object.create(null);\n \t\t__webpack_require__.r(ns);\n \t\tObject.defineProperty(ns, 'default', { enumerable: true, value: value });\n \t\tif(mode & 2 && typeof value != 'string') for(var key in value) __webpack_require__.d(ns, key, function(key) { return value[key]; }.bind(null, key));\n \t\treturn ns;\n \t};\n\n \t// getDefaultExport function for compatibility with non-harmony modules\n \t__webpack_require__.n = function(module) {\n \t\tvar getter = module && module.__esModule ?\n \t\t\tfunction getDefault() { return module['default']; } :\n \t\t\tfunction getModuleExports() { return module; };\n \t\t__webpack_require__.d(getter, 'a', getter);\n \t\treturn getter;\n \t};\n\n \t// Object.prototype.hasOwnProperty.call\n \t__webpack_require__.o = function(object, property) { return Object.prototype.hasOwnProperty.call(object, property); };\n\n \t// __webpack_public_path__\n \t__webpack_require__.p = \"\";\n\n\n \t// Load entry module and return exports\n \treturn __webpack_require__(__webpack_require__.s = \"./src/extension.ts\");\n","module.exports = require( './lib/connected-domain' );","/**\n * calculate all the connected domains based on the given two-dimensional array\n */\n\n/**\n * @param {Array} tdArray\n * @param {Function} indicator It receive the raw point data as the first parameter and decide what kind of domain the point belongs to, it should return a string as a domain identifier.\n * @param {Boolean} hardlink If use hard link. Default to false.\n * @return {Object} [{ bounding: { w: 12, h: 19, x: 0, y: 1 }, points: [ { x: 1, y: 2, point: {} } ], identifier: 'blue', domainId: 1 } ]\n */\nmodule.exports = function( tdArray, indicator, hardlink ){\n\n hardlink = hardlink || false;\n\n if( !tdArray ){\n throw new Error( 'tdArray must be provided' );\n }\n\n if( !indicator ){\n throw new Error( 'indicator must be provided' );\n }\n\n // clone 一份数据,因为需要对饮用进行修改,方便执行\n tdArray = JSON.parse( JSON.stringify( tdArray ) );\n\n // Result\n var domains = {};\n var domainUUID = 0;\n var pointsHash = {};\n\n // 遍历数组,划分domain\n\n tdArray.forEach(function( row, y ){\n\n row.forEach(function( colItem, x ){\n\n // get the current point identifier.\n var identifier = indicator( colItem, x, y );\n\n // get neighbours\n // Except for Undefined every data type is valid.\n var neighbours = [];\n\n // top neighbour\n if( tdArray[ y - 1 ] && tdArray[ y - 1 ][ x ] !== undefined ){\n neighbours.push( pointsHash[ x + '_' + ( y - 1 ) ] );\n }\n\n // left neighbour\n if( row[ x - 1 ] !== undefined ){\n neighbours.push( pointsHash[ ( x - 1 ) + '_' + y ] );\n }\n\n // soft link will treat corner link as domain link.\n if( !hardlink ){\n // top left neighbour\n if( tdArray[ y - 1 ] && tdArray[ y - 1 ][ x - 1 ] !== undefined ){\n neighbours.push( pointsHash[ ( x - 1 ) + '_' + ( y - 1 ) ] );\n }\n\n // top right neighbour\n if( tdArray[ y - 1 ] && tdArray[ y - 1 ][ x + 1 ] !== undefined ){\n neighbours.push( pointsHash[ ( x + 1 ) + '_' + ( y - 1 ) ] );\n }\n }\n\n if( neighbours.length ){\n var matched = false;\n\n neighbours.forEach(function( neighbour ){\n\n if( neighbour.identifier == identifier ){\n\n // If the neighbour is the first neighbour has the same identifier\n if( !matched ){\n addPointToDomain( colItem, x, y, neighbour.domainId );\n matched = true;\n }\n\n // If more than one neighbour matched, check if these neighbours belong to the same domain\n // If not, merge these domains since they connects to each other.\n else {\n var colItemPoint = pointsHash[ x + '_' + y ];\n if( neighbour.domainId != colItemPoint.domainId ){\n mergeDomains( neighbour.domainId, colItemPoint.domainId );\n }\n }\n }\n });\n\n if( !matched ){\n addNewDomain( colItem, x, y, identifier );\n }\n }\n else {\n addNewDomain( colItem, x, y, identifier );\n }\n });\n });\n\n // some summary\n var result = {\n domains: [],\n totalDomains: 0,\n groupByIdentifier: {},\n totalIdentifiers: 0\n };\n\n var domainId = null;\n var identifier = null;\n var domain = null;\n for( domainId in domains ){\n domain = domains[ domainId ];\n domain.bounding = calculateBounding( domain.points );\n identifier = domain.identifier;\n\n result.domains.push( domain );\n result.totalDomains++;\n\n if( !( identifier in result.groupByIdentifier ) ){\n result.groupByIdentifier[ identifier ] = [];\n result.totalIdentifiers++;\n }\n\n result.groupByIdentifier[ identifier ].push( domain );\n }\n\n\n function calculateBounding( points ){\n\n var minX = null;\n var minY = null;\n var maxX = null;\n var maxY = null;\n\n points.forEach(function( point ){\n\n if( minX === null || point.x < minX ){\n minX = point.x;\n }\n\n if( minY === null || point.y < minY ){\n minY = point.y;\n }\n\n if( maxX === null || point.x > maxX ){\n maxX = point.x;\n }\n\n if( maxY === null || point.y > maxY ){\n maxY = point.y;\n }\n });\n\n var w = maxX - minX;\n var h = maxY - minY;\n\n return {\n x: minX,\n y: minY,\n w: w,\n h: h\n };\n }\n\n /**\n *\n * @param point\n * @param x\n * @param y\n * @param identifier\n */\n function addNewDomain( point, x, y, identifier ){\n\n var newDomain = {\n identifier: identifier,\n domainId: ++domainUUID,\n bounding: {},\n points: []\n };\n\n var newPoint = {\n value: point,\n x: x,\n y: y,\n identifier: identifier,\n domainId: newDomain.domainId\n };\n\n pointsHash[ x + '_' + y ] = {\n value: point,\n identifier: identifier,\n domainId: newDomain.domainId\n };\n\n newDomain.points.push( newPoint );\n\n domains[ newDomain.domainId ] = newDomain;\n }\n\n /**\n * add a point to a existing domain, and attach properties domainId and identifier to point.\n * @param point\n * @param x\n * @param y\n * @param domainId\n */\n function addPointToDomain( point, x, y, domainId ){\n\n var domain = domains[ domainId ];\n var newPoint = {\n value: point,\n x: x,\n y: y,\n identifier: domain.identifier,\n domainId: domainId\n };\n\n pointsHash[ x + '_' + y ] = {\n value: point,\n identifier: domain.identifier,\n domainId: domainId\n };\n\n domain.points.push( newPoint );\n }\n\n /**\n * 将 domainB 合并到 domainA\n * @param domainAId\n * @param domainBId\n */\n function mergeDomains( domainAId, domainBId ){\n\n var domainA = domains[ domainAId ];\n var domainB = domains[ domainBId ];\n\n if( domainA.identifier == domainB.identifier ){\n // 更新 domainB 的domainId\n\n domainB.domainId = domainA.domainId;\n\n domainB.points.forEach(function( point ){\n point.domainId = domainA.domainId;\n pointsHash[ point.x + '_' + point.y ].domainId = domainA.domainId;\n });\n\n domainA.points = domainA.points.concat( domainB.points );\n\n // 删除domainB\n delete domains[ domainBId ];\n }\n }\n\n return result;\n};","module.exports = require('./lib');\n","var ChildProcess = require('child_process');\nvar IS_WIN = process.platform === 'win32';\nvar TableParser = require('table-parser');\n/**\n * End of line.\n * Basically, the EOL should be:\n * - windows: \\r\\n\n * - *nix: \\n\n * But i'm trying to get every possibilities covered.\n */\nvar EOL = /(\\r\\n)|(\\n\\r)|\\n|\\r/;\nvar SystemEOL = require('os').EOL;\n\n/**\n * Execute child process\n * @type {Function}\n * @param {String[]} args\n * @param {Function} callback\n * @param {Object=null} callback.err\n * @param {Object[]} callback.stdout\n */\n\nvar Exec = module.exports = exports = function (args, callback) {\n var spawn = ChildProcess.spawn;\n\n // on windows, if use ChildProcess.exec(`wmic process get`), the stdout will gives you nothing\n // that's why I use `cmd` instead\n if (IS_WIN) {\n\n var CMD = spawn('cmd');\n var stdout = '';\n var stderr = null;\n\n CMD.stdout.on('data', function (data) {\n stdout += data.toString();\n });\n\n CMD.stderr.on('data', function (data) {\n\n if (stderr === null) {\n stderr = data.toString();\n }\n else {\n stderr += data.toString();\n }\n });\n\n CMD.on('exit', function () {\n\n var beginRow;\n stdout = stdout.split(EOL);\n\n // Find the line index for the titles\n stdout.forEach(function (out, index) {\n if (out && typeof beginRow == 'undefined' && out.indexOf('CommandLine') === 0) {\n beginRow = index;\n }\n });\n\n // get rid of the start (copyright) and the end (current pwd)\n stdout.splice(stdout.length - 1, 1);\n stdout.splice(0, beginRow);\n\n callback(stderr, stdout.join(SystemEOL) || false);\n });\n\n CMD.stdin.write('wmic process get ProcessId,ParentProcessId,CommandLine \\n');\n CMD.stdin.end();\n }\n else {\n if (typeof args === 'string') {\n args = args.split(/\\s+/);\n }\n const child = spawn('ps', args);\n var stdout = '';\n var stderr = null;\n\n child.stdout.on('data', function (data) {\n stdout += data.toString();\n });\n\n child.stderr.on('data', function (data) {\n\n if (stderr === null) {\n stderr = data.toString();\n }\n else {\n stderr += data.toString();\n }\n });\n\n child.on('exit', function () {\n if (stderr) {\n return callback(stderr.toString());\n }\n else {\n callback(null, stdout || false);\n }\n });\n }\n};\n\n/**\n * Query Process: Focus on pid & cmd\n * @param query\n * @param {String|String[]} query.pid\n * @param {String} query.command RegExp String\n * @param {String} query.arguments RegExp String\n * @param {String|array} query.psargs\n * @param {Function} callback\n * @param {Object=null} callback.err\n * @param {Object[]} callback.processList\n * @return {Object}\n */\n\nexports.lookup = function (query, callback) {\n\n /**\n * add 'lx' as default ps arguments, since the default ps output in linux like \"ubuntu\", wont include command arguments\n */\n var exeArgs = query.psargs || ['lx'];\n var filter = {};\n var idList;\n\n // Lookup by PID\n if (query.pid) {\n\n if (Array.isArray(query.pid)) {\n idList = query.pid;\n }\n else {\n idList = [query.pid];\n }\n\n // Cast all PIDs as Strings\n idList = idList.map(function (v) {\n return String(v);\n });\n\n }\n\n\n if (query.command) {\n filter['command'] = new RegExp(query.command, 'i');\n }\n\n if (query.arguments) {\n filter['arguments'] = new RegExp(query.arguments, 'i');\n }\n\n if (query.ppid) {\n filter['ppid'] = new RegExp(query.ppid);\n }\n\n return Exec(exeArgs, function (err, output) {\n if (err) {\n return callback(err);\n }\n else {\n var processList = parseGrid(output);\n var resultList = [];\n\n processList.forEach(function (p) {\n\n var flt;\n var type;\n var result = true;\n\n if (idList && idList.indexOf(String(p.pid)) < 0) {\n return;\n }\n\n for (type in filter) {\n flt = filter[type];\n result = flt.test(p[type]) ? result : false;\n }\n\n if (result) {\n resultList.push(p);\n }\n });\n\n callback(null, resultList);\n }\n });\n};\n\n/**\n * Kill process\n * @param pid\n * @param {Object|String} signal\n * @param {String} signal.signal\n * @param {number} signal.timeout\n * @param next\n */\n\nexports.kill = function( pid, signal, next ){\n //opts are optional\n if(arguments.length == 2 && typeof signal == 'function'){\n next = signal;\n signal = undefined;\n }\n\n var checkTimeoutSeconds = (signal && signal.timeout) || 30;\n\n if (typeof signal === 'object') {\n signal = signal.signal;\n }\n\n try {\n process.kill(pid, signal);\n } catch(e) {\n return next && next(e);\n }\n\n var checkConfident = 0;\n var checkTimeoutTimer = null;\n var checkIsTimeout = false;\n\n function checkKilled(finishCallback) {\n exports.lookup({ pid: pid }, function(err, list) {\n if (checkIsTimeout) return;\n\n if (err) {\n clearTimeout(checkTimeoutTimer);\n finishCallback && finishCallback(err);\n } else if(list.length > 0) {\n checkConfident = (checkConfident - 1) || 0;\n checkKilled(finishCallback);\n } else {\n checkConfident++;\n if (checkConfident === 5) {\n clearTimeout(checkTimeoutTimer);\n finishCallback && finishCallback();\n } else {\n checkKilled(finishCallback);\n }\n }\n });\n }\n\n next && checkKilled(next);\n\n checkTimeoutTimer = next && setTimeout(function() {\n checkIsTimeout = true;\n next(new Error('Kill process timeout'));\n }, checkTimeoutSeconds * 1000);\n};\n\n/**\n * Parse the stdout into readable object.\n * @param {String} output\n */\n\nfunction parseGrid(output) {\n if (!output) {\n return [];\n }\n return formatOutput(TableParser.parse(output));\n}\n\n/**\n * format the structure, extract pid, command, arguments, ppid\n * @param data\n * @return {Array}\n */\n\nfunction formatOutput(data) {\n var formatedData = [];\n data.forEach(function (d) {\n var pid = ( d.PID && d.PID[0] ) || ( d.ProcessId && d.ProcessId[0] ) || undefined;\n var cmd = d.CMD || d.CommandLine || d.COMMAND || undefined;\n var ppid = ( d.PPID && d.PPID[0] ) || ( d.ParentProcessId && d.ParentProcessId[0] ) || undefined;\n\n if (pid && cmd) {\n var command = cmd[0];\n var args = '';\n\n if (cmd.length > 1) {\n args = cmd.slice(1);\n }\n\n formatedData.push({\n pid: pid,\n command: command,\n arguments: args,\n ppid: ppid\n });\n }\n });\n\n return formatedData;\n}\n","module.exports = require( './lib/index' );","/**\n *\n * 1, define the edge ( begin and end ) of every title field\n * 2, parse all the lines except the title line, get all the connected-domains\n * 3, group all the connected-domains vertically overlapped.\n * 4, a domain group belongs to a title field if they vertically overlapped\n * 5, calculate all the edge info through the group domain and title field relations.\n */\nvar ConnectedDomain = require('connected-domain');\nvar EMPTY_EX = /\\s/;\n\n/**\n * The output sting of cmd to parse\n * @param output\n * @returns {Array}\n */\nmodule.exports.parse = function (output) {\n\n // Split into lines\n // Basically, the EOL should be:\n // - windows: \\r\\n\n // - *nix: \\n\n // But i'm trying to get every possibilities covered.\n var linesTmp = output.split(/(\\r\\n)|(\\n\\r)|\\n|\\r/);\n\n // valid lines\n var lines = [];\n // title field info, mapped with filed name.\n var titleInfo = {};\n // the two dimensional array of the lines\n var twoDimArray = [];\n\n // get rid of all the empty lines.\n linesTmp.forEach(function (line) {\n if (line && line.trim()) {\n lines.push(line);\n }\n });\n\n // build title fields edge info\n // build two dimensional array for Connected-Domain to parse.\n lines.forEach(function (line, index) {\n\n // Treat the first line as the title fields line\n if (index == 0) {\n var fields = line.split(/\\s+/);\n\n // record the beginning and ending for each field\n fields.forEach(function (field, idx) {\n\n if (field) {\n var info = titleInfo[field] = {};\n var indexBegin = line.indexOf(field);\n var indexEnd = indexBegin + field.length;\n\n if (idx == 0) {\n info.titleBegin = 0;\n }\n else {\n info.titleBegin = indexBegin;\n }\n\n if (idx == fields.length - 1) {\n info.titleEnd = line.length - 1;\n }\n else {\n info.titleEnd = indexEnd;\n }\n }\n });\n }\n else {\n twoDimArray[index - 1] = line.split('');\n }\n });\n\n // In the connected-domain aspect of view, all the blanks are connected, and all the non-blanks are connected.\n var connectedDomains = ConnectedDomain(twoDimArray, function (value) {\n if (EMPTY_EX.test(value)) {\n return -1;\n }\n else {\n return 1;\n }\n }, true);\n\n // all the connected domains grouped if they are vertically overlapped.\n var valuesDomainsVerticalGroups = [];\n\n // sore the domain list make 'x' in ascending order, it will prevent the situation that:\n // 1, two domains are not overlapped, so two groups are created for them at first\n // 2, another domain is found overlapped with both of the domains at the first step.\n // 3, In this situation the three groups have to be merged, which is complicated to implement.\n //\n // If the list is sorted in this order, this situation can't happen, because:\n // - 1, If two non-overlapped domains A, B ( the \"x\" value of A less than B ) are found first.\n // - 2, Since the list is in 'x' ascending order, the 'x' values of the following domains must larger or equal to the \"x\" of B, which means they will never overlapped with domain A.\n // - 3, So this situation can't happen.\n connectedDomains.domains.sort(function (a, b) {\n return a.bounding.x - b.bounding.x;\n });\n\n // Group domains vertically overlapped.\n connectedDomains.domains.forEach(function (domain) {\n // only handle un-empty domain\n if (domain.identifier === 1) {\n var overlapped = false;\n\n // If overlapped\n valuesDomainsVerticalGroups.forEach(function (group) {\n var bounding = domain.bounding;\n var left = bounding.x;\n var right = bounding.x + bounding.w;\n\n if (overlap(left, right, group.begin, group.end)) {\n\n overlapped = true;\n group.domains.push(domain);\n group.begin = group.begin > left ? left : group.begin;\n group.end = group.end < right ? right : group.end;\n }\n });\n\n // If not overlapped with any group, then create a new group\n if (!overlapped) {\n valuesDomainsVerticalGroups.push({\n begin: domain.bounding.x,\n end: domain.bounding.x + domain.bounding.w,\n domains: [domain]\n });\n }\n }\n });\n\n // connect all the groups to the title fields\n valuesDomainsVerticalGroups.forEach(function (group) {\n var title = null;\n var info = null;\n var overlapped = false;\n\n var minimunLeftDistance = null;\n var nearestLeftTitle = null;\n var distance = null;\n\n for (title in titleInfo) {\n info = titleInfo[title];\n\n /**\n * The calculation below is to find the nearest left title field to the group, in case no overlapped title field found.\n */\n if (group.begin > info.titleBegin) {\n distance = group.begin - info.titleBegin;\n\n if (!nearestLeftTitle || ( distance < minimunLeftDistance )) {\n nearestLeftTitle = title;\n minimunLeftDistance = distance;\n }\n }\n\n if (overlap(group.begin, group.end, info.titleBegin, info.titleEnd)) {\n\n overlapped = true;\n info.titleBegin = info.titleBegin > group.begin ? group.begin : info.titleBegin;\n info.titleEnd = info.titleEnd < group.end ? group.end : info.titleEnd;\n }\n }\n\n // Groups not match any title field belongs to the nearest left title field\n if (!overlapped && nearestLeftTitle) {\n var nearestTitleField = titleInfo[nearestLeftTitle];\n nearestTitleField.titleBegin = nearestTitleField.titleBegin > group.begin ? group.begin : nearestTitleField.titleBegin;\n nearestTitleField.titleEnd = nearestTitleField.titleEnd < group.end ? group.end : nearestTitleField.titleEnd;\n\n }\n });\n\n // The final result\n var result = [];\n\n // Since we have got all the title bounding edges, we can split all the lines into values now\n lines.forEach(function (line, index) {\n // skip the first line\n if (index > 0) {\n\n var lineItem = {};\n var title = null;\n var info = null;\n var value = null;\n for (title in titleInfo) {\n info = titleInfo[title];\n value = line.substring(info.titleBegin, info.titleEnd + 1);\n lineItem[title] = splitValue(value.trim());\n }\n\n result.push(lineItem);\n }\n });\n\n return result;\n};\n\n/**\n * Test if two bounding overlapped vertically\n * @param begin1\n * @param end1\n * @param begin2\n * @param end2\n * @returns {boolean}\n */\nfunction overlap(begin1, end1, begin2, end2) {\n return ( begin1 > begin2 && begin1 < end2 ) || // 2--1--2--1 or 2--1--1--2\n ( end1 > begin2 && end1 < end2 ) || // 1--2--1--2 or 2--1--1--2\n ( begin1 <= begin2 && end1 >= end2 );// 21--12 or 1--2--2--1\n}\n\n/**\n * transform a string value into array. It's not just split(), but also to consider some chunk that wrapped with `\"`, like below:\n * \"C:\\Program Files\\Google\\Chrome\\Application\\chrome.exe\" --type=renderer --lang=zh-CN, `C:\\Program Files\\Google\\Chrome\\Application\\chrome.exe` should be treated as a whole,\n * also, be careful don't be mislead by format like `--name=\"neekey\"`, even more complicated: `--name=\"Neekey Ni\"`\n * so, `\"C:\\Program Files\\Internet Explorer\\iexplore.exe\" --name=\"Jack Neekey\"` should split into:\n * - C:\\Program Files\\Internet Explorer\\iexplore.exe // without `\"`\n * - --name=\"Jack Neekey\" // with `\"`\n */\nfunction splitValue(value) {\n\n var match = value.match(/\"/g);\n\n // If only one \" found, then just ignore it\n if (!match || match.length == 1) {\n return value.split(/\\s+/);\n }\n else {\n var result = [];\n var chunk = null;\n var ifInWrappedChunk = false;\n var ifInPureWrappedChunk = false;\n var quotaCount = 0;\n\n // If the match length is a even, than nothing special, if a odd, ignore the last one.\n var maxQuotaCount = match.length % 2 == 0 ? match.length : match.length - 1;\n\n var previousItem = null;\n var values = value.split('');\n\n values.forEach(function (item, index) {\n\n if (item !== ' ') {\n\n if (item === '\"') {\n // quota chunk begin\n if (ifInWrappedChunk === false && quotaCount <= maxQuotaCount) {\n ifInWrappedChunk = true;\n quotaCount++;\n\n // pure quota chunk begin\n if (previousItem === ' ' || previousItem === null) {\n ifInPureWrappedChunk = true;\n chunk = '';\n }\n // normal continue\n else {\n chunk += item;\n }\n }\n // quota chunk end\n else if (ifInWrappedChunk === true) {\n ifInWrappedChunk = false;\n quotaCount++;\n\n // pure quota chunk end\n if (ifInPureWrappedChunk === true) {\n ifInPureWrappedChunk = false;\n result.push(chunk);\n chunk = null;\n }\n // normal continue\n else {\n chunk += item;\n }\n }\n }\n // normal begin\n else if (ifInWrappedChunk === false && ( previousItem === ' ' || previousItem === null )) {\n chunk = item;\n }\n // normal or quota chunk continue.\n else {\n chunk += item;\n }\n }\n // quota chunk continue, in quota chunk, blank is valid.\n else if (ifInWrappedChunk) {\n chunk += item;\n }\n // if not in quota chunk, them a blank means an end. But make sure chunk is exist, cause that could be blanks at the beginning.\n else if (chunk !== null) {\n result.push(chunk);\n chunk = null;\n }\n\n previousItem = item;\n\n // If this is the last one, but chunk is not end\n if (index == ( values.length - 1 ) && chunk !== null) {\n result.push(chunk);\n chunk = null;\n }\n });\n\n return result;\n }\n}\n","import * as vscode from 'vscode';\nimport { fileURLToPath } from 'url';\nimport * as path from 'path';\nimport * as fs from 'fs';\nimport * as ps from 'ps-node';\n\nexport function activate(context: vscode.ExtensionContext) {\n\n\tlet PORT = 6006;\n\tconst host = 'localhost';\n\n //create disposable variable type, registers awaken command & opens webview\n\tlet disposable = vscode.commands.registerCommand('extension.aesopAwaken', () => {\n\n\t\t//define a path to the root working directory of the user\n\t\tconst rootDir = fileURLToPath(vscode.workspace.workspaceFolders[0].uri.toString(true));\n\n\t\t//check first to ensure that Storybook has been depended into the current working directory\n\t\tfs.access(path.join(rootDir, '/node_modules/@storybook'), (err) => {\n\n\t\t\t//if the filepath isn't found, show the user what Aesop is reading as the root path\n\n\t\t\tif (err) {\n\t\t\t\tvscode.window.showErrorMessage(`Aesop could not find Storybook as a dependency in the active folder, ${rootDir}`);\n\t\t\t}\telse {\n\t\t\t\t//check to see if a storybook node process is already running\n\t\t\t\tps.lookup({\n\t\t\t\t\tcommand: 'node',\n\t\t\t\t\tpsargs: 'ux'\n\t\t\t\t}, (err, resultList) => {\n\t\t\t\t\tif (err){\n\t\t\t\t\t\tvscode.window.showErrorMessage(`Failed looking for running Node processes. Error: ${err}`);\n\t\t\t\t\t} else {\n\t\t\t\t\t\tlet foundSb = false;\n\t\t\t\t\t\t//if the process lookup was able to find running processes, iterate through to review them\n\t\t\t\t\t\tresultList.forEach((process) => {\n\n\t\t\t\t\t\t\t// ---> OUTPUT LOGGER <--- //\n\t\t\t\t\t\t\tfs.writeFile(path.join(rootDir, 'YOLO.txt'),\n\t\t\t\t\t\t\t`Here is the JSON-stringified version of a process:\\n${JSON.stringify(process)}\\n`,\n\t\t\t\t\t\t\t(err) => {console.log(`Couldn't output process information to YOLO.txt: ${err}`)});\n\t\t\t\t\t\t\tvscode.window.showInformationMessage('Check YOLO.txt for output information');\n\n\t\t\t\t\t\t\t//check if any running processes are using the start-storybook script\n\t\t\t\t\t\t\tif(process.arguments[0].includes('storybook')){\n\t\t\t\t\t\t\t\tfoundSb = true;\n\t\t\t\t\t\t\t\t//stretch goal: check for multiple instances of storybook and reconcile\n\t\t\t\t\t\t\t\t//if so, extract port number and use that value to populate the webview with that contents\n\t\t\t\t\t\t\t\n\t\t\t\t\t\t\t\tconst pFlagIndex = process.arguments.indexOf('-p');\n\t\t\t\t\t\t\t\tif (pFlagIndex !== -1){\n\t\t\t\t\t\t\t\t\tPORT = Number(process.arguments[pFlagIndex+1]);\n\t\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\t\t// ---> OUTPUT LOGGER <--- //\n\t\t\t\t\t\t\t\tfs.appendFile(path.join(rootDir, 'YOLO.txt'), `This process matches for 'storybook'search string:\\n\n\t\t\t\t\t\t\t\tPID: ${process.pid}, COMMAND:${process.command}, ARGUMENTS: ${process.arguments}\\n`, (err) => {console.log(err)});\n\t\t\t\t\t\t\t\t\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t})\n\n\t\t\t\t\t\tif (foundSb === false){\n\t\t\t\t\t\t\t\t//if no processes match 'storybook', we will have to spin up the storybook server\n\t\t\t\t\t\t\t\t//starts by extracting the existing storybook script in the package.json\n\t\t\t\t\t\t\t\tfs.readFile(path.join(rootDir, 'package.json'), (err, data) => {\n\t\t\t\t\t\t\t\t\tif (err){\n\t\t\t\t\t\t\t\t\t\tvscode.window.showErrorMessage(`Does this root folder contain a \"package.json\" file?`);\n\t\t\t\t\t\t\t\t\t}\telse {\n\t\t\t\t\t\t\t\t\t\t//enter the package.JSON file and retrieve its contents as a string\n\t\t\t\t\t\t\t\t\t\tlet packageJSONText = JSON.parse(data.toString());\n\t\t\t\t\t\t\t\t\t\tlet storybookScript = packageJSONText.scripts.storybook;\n\n\t\t\t\t\t\t\t\t\t\t// // ---> OUTPUT LOGGER <--- //\n\t\t\t\t\t\t\t\t\t\t// fs.appendFile(path.join(rootDir, 'YOLO.txt'), `Here is the JSON parsed version:\\n\n\t\t\t\t\t\t\t\t\t\t// ${packageJSONText.scripts}\\n\n\t\t\t\t\t\t\t\t\t\t// ${packageJSONText.scripts.storybook}`, (err) => {console.log(err)});\n\n\t\t\t\t\t\t\t\t\t\t// // ---> OUTPUT LOGGER <--- //\n\t\t\t\t\t\t\t\t\t\t// fs.appendFile(path.join(rootDir, 'YOLO.txt'), `Here is the full contents of the package.json file from the user's workspace folder:\\n${packageJSONText}\\n`, (err) => {console.log(err)});\n\n\t\t\t\t\t\t\t\t\t\t// // ---> OUTPUT LOGGER <--- //\n\t\t\t\t\t\t\t\t\t\t// fs.appendFile(path.join(rootDir, 'YOLO.txt'), `This is what our readFile function (line 72) returns when it attempts to retrieve (line 82) the \"storybook\" script from your app's package.json:\\n${retrievedScript}\\n`, (err) => {console.log(err)});\n\n\t\t\t\t\t\t\t\t\t\t//iterate through that text string and parse out important flags\n\t\t\t\t\t\t\t\t\t\t//it is more helpful to split it into an array separated by whitespace to grab these\n\t\t\t\t\t\t\t\t\t\tlet retrievedScriptArray = storybookScript.split(' ');\n\t\t\t\t\t\t\t\t\t\tfor (let i = 0; i < retrievedScriptArray.length; i++){\n\t\t\t\t\t\t\t\t\t\t\t//add flags\n\t\t\t\t\t\t\t\t\t\t\tif (retrievedScriptArray[i] === '-p'){\n\t\t\t\t\t\t\t\t\t\t\t\tPORT = parseInt(retrievedScriptArray[i+1]);\n\t\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t})\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t})\n\t\t\t}\n\t\t})\n\n\t\t//set the extension context equal to \"aesop is running\"\n\t\t// vscode.commands.executeCommand(\"setContext\", \"is-running-aesop\", true);\n\n\t\t//still inside our disposable variable, let's create the webview panel\n\t\tconst panel : vscode.WebviewPanel = vscode.window.createWebviewPanel(\n\t\t\t'aesop-sb',\n\t\t\t'Aesop',\n\t\t\tvscode.ViewColumn.Two,\n\t\t\t{\n\t\t\t\tenableCommandUris: true,\n\t\t\t\tenableScripts: true,\n\t\t\t\t// portMapping: [\n\t\t\t\t// \t{ webviewPort: PORT, extensionHostPort: PORT}\n\t\t\t\t// ]\n\t\t\t}\n\t\t);\n\n\t\tpanel.webview.html =\n\t\t\t`\n\t\t\t\n\t\t\t\t\n\t\t\t\t\t\n\t\t\t\t\t\n\t\t\t\t\tAesop\n\t\t\t\t\n\t\t\t\t\n\t\t\t\t\t\n\t\t\t\t\n\t\t\t`\n\t})\n\n\tcontext.subscriptions.push(disposable);\n};\n\nexport function deactivate() {\n\t\n}\n\n/*\nto-do:\n\tfigure out how to iteratively call sb scripts within our webview\n\twebview messages / scripts to reload\n\tfigure out how to use a tsx rule in webpack to execute scripts\n\tsignal babel to interpret this block as tsx, e.g. something like: //@tsx babel//\n\n\n\t\n\t\t\t\t\t\tvscode.tasks.registerTaskProvider('runStorybook', {\n\t\t\t\t\t\t\t\t\t\t\t\tprovideTasks(token?: vscode.CancellationToken) {\n\t\t\t\t\t\t\t\t\t\t\t\t\t\treturn [\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tnew vscode.Task({type: 'runStorybook'}, vscode.TaskScope.Workspace,\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\"Aesop Chronicle\", \"aesop\", new vscode.ShellExecution(`npm run storybook --ci`))\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t];\n\t\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\tresolveTask(task: vscode.Task, token?: vscode.CancellationToken) {\n\t\t\t\t\t\t\t\t\t\t\t\t\t\treturn task;\n\t\t\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t\t\t});\n\n\t\t\t\t\t\t\t\t\t\t\t//define the script text to execute to the virtual terminal instance\n\t\t\t\t\t\t\t\t\t\t\tconst bootScript = `storybook --ci`;\n\t\t\t\t\t\t\t\t\t\t\tconst bootStorybook = new vscode.ProcessExecution(bootScript, {cwd: rootDir});\n\n\t\t\t\t\t\t\t\t\t\t\t//now create a virtual terminal and execute our special npm script for it\n\t\t\t\t\t\t\t\t\t\t\t//this first requires creating an eventEmitter that will fire that script\n\t\t\t\t\t\t\t\t\t\t\tconst scriptEmitter = new vscode.EventEmitter();\n\t\t\t\t\t\t\t\n\t\t\t\t\t\t\t\t\t\t\t//we also define a slave process Pseudoterminal (allowing Aesop to control the terminal)\n\t\t\t\t\t\t\t\t\t\t\tconst pty: vscode.Pseudoterminal = {\n\t\t\t\t\t\t\t\t\t\t\t\tonDidWrite: scriptEmitter.event,\n\t\t\t\t\t\t\t\t\t\t\t\topen: () =>\tscriptEmitter.fire(bootScript),\n\t\t\t\t\t\t\t\t\t\t\t\tclose: () => {},\n\t\t\t\t\t\t\t\t\t\t\t\thandleInput: data => new vscode.ShellExecution(data)\n\t\t\t\t\t\t\t\t\t\t\t};\n\n\t\t\t\t\t\t\t\t\t\t\t//should this just be an active terminal/shellExecution?\n\t\t\t\t\t\t\t\t\t\t\tconst virtualTerminal = vscode.window.createTerminal({name: 'sb-runner', pty});\n\n//THIS WORKS, but we have no access to the DOM inside our webview//\n\t//now let's read SB's outputted index.html file, and parse out what we need\n\t\tfs.readFile(path.join(rootDir, '/node_modules/@storybook/core/dist/public/index.html'), (err, data) => {\n\t\t\tif (err) console.error(err);\n\t\t\telse {\n\t\t\t\tlet pulledHTML = data.toString();\n\t\t\t\tlet targetPoint = pulledHTML.indexOf('');\n\t\t\t\tlet firstHalf = pulledHTML.slice(0, targetPoint);\n\t\t\t\tlet secondHalf = pulledHTML.slice(targetPoint);\n\t\t\t\tpulledHTML = firstHalf.concat(payloadScript).concat(secondHalf);\n\t\t\t\tfs.writeFile(path.join(rootDir, '/node_modules/@storybook/core/dist/public/index.html'), pulledHTML, (err) => {\n\t\t\t\t\tif (err) console.error(err);\n\t\t\t\t\telse {\n\t\t\t\t\t\tvscode.window.showInformationMessage('Successfully injected script');\n\t\t\t\t\t};\n\t\t\t\t});\n\t\t\t}\n\t\t});\n\n\t//declare an empty array (of strings) to push our scripts to during the next part\n\t\tconst scriptArray : Array = [];\n\t\t//define a path to the root working directory of the user\n\t\tconst rootDir = fileURLToPath(vscode.workspace.workspaceFolders[0].uri.toString(true));\n\t\t//now let's read SB's outputted index.html file, and parse out what we need\n\t\tfs.readFile(path.join(rootDir, '/node_modules/@storybook/core/dist/public/index.html'), (err, data) => {\n\t\t\tif (err) console.error(err);\n\t\t\telse {\n\t\t\t\t//if we've read the HTML file, take its contents and stringify it\n\t\t\t\tlet outputFile = data.toString();\n\t\t\t\t// this log shows what our eventual permutations would look like as we carve out the scripts\n\t\t\t\t// vscode.window.showWarningMessage(`what's in it: ${outputFile.slice(outputFile.indexOf('')+6, outputFile.indexOf(''))} \\n`)\n\t\t\t\t//split out the body section of the retrieved html file\n\t\t\t\toutputFile = outputFile.slice(outputFile.indexOf('')+6, outputFile.indexOf(''));\n\t\t\t\tvscode.window.showWarningMessage(`${outputFile} \\n`)\n\n\t\t\t\t//this loop will peel out all the scripts so long as there are any to rip out\n\t\t\t\twhile (outputFile.includes(`\" tags behind\n\t\t\t\t\tlet temp = outputFile.slice(outputFile.indexOf(``));\n\t\t\t\t\tscriptArray.push(temp);\n\t\t\t\t\toutputFile = outputFile.slice(outputFile.indexOf(`\">`)+10);\n\t\t\t\t}\n\t\t\t};\n\t\t});\n\n
\n
\t\n\t
\n\t\n\t\n\t\n
\n\n\tdisposable = vscode.commands.registerCommand('extension.getStories', () => {\n\t\tbuild a command that retrieves Storybook files on startup\n\t\tcan be executed later if Storybook server is spun up after the extension opens\n\t\t\n\t\talso register this command at startup to crawl the file path\n\t\t${vscode.commands.executeCommand('extension.getStories')}\n\t\tvscode.window.showInformationMessage('Aesop is reading from your Storybook.');\n\n\t\tdefine a path to SB webpack bundle outputs (in user workspace /node_modules/ folder)\n\t\tif (vscode.workspace.workspaceFolders[0] !== undefined){\n\t\t\tconst distGlob = new vscode.RelativePattern(vscode.workspace.workspaceFolders[0], \"**(remove)/node_modules/@storybook/core/dist/public\");\n\t\t\t//instantiate a watcher to listen for fs path changes (e.g. file creation/update)\n\t\t\t//bools = options for ignoreCreateEvents?, ignoreChangeEvents?, ignoreDeleteEvents?\t\n\t\t\tconst observer = vscode.workspace.createFileSystemWatcher(distGlob, false, false, false);\n\t\t\t// observer.onDidChange = //resolve//;\t\t// observer.onDidCreate = //resolve//;\n\t\t\t//extract index.html file that outputs into SB's preview pane\n\t\t\tconst htmlGlob = new vscode.RelativePattern(vscode.workspace.workspaceFolders[0], \"*(remove)/node_modules/@storybook/core/dist/public/*.html\");\n\t\t\t//extract necessary bundle scripts to leverage in-app dependencies\n\t\t\tconst scriptGlob = new vscode.RelativePattern(vscode.workspace.workspaceFolders[0], \"*(remove)/node_modules/@storybook/core/dist/public/*.js\");\n\n\t\t\tconsole.log(vscode.Uri.file(fileURLToPath(`/node_modules/@storybook/core/dist/public`)));\n\n\t\t\t//do we need to resolve the Storybook UI script from the /dll/ folder?\n\t\t\t//if extract methods above fail, determine logic to parse out HTML/.js scripts (index 0?);\n\t\t\t//retrieve files with findFiles/relativeFilePath\n\t\t\tconst arrayOfScripts = vscode.workspace.findFiles(distGlob, null, 100);\n\t\t\t//dev check: have we successfully pulled down script files?\n\t\t\t//if so, should we then store them locally, or is there no point?\n\t\t\tif (arrayOfScripts !== undefined){\n\t\t\t\tvscode.window.showInformationMessage(\"Hey, dog: \" + `${arrayOfScripts}`);\n\t\t\t}\n\n\t\t\tvscode.window.showInformationMessage(`\n\t\t\trootPath: ${vscode.workspace.workspaceFolders[0]},\n\t\t\tvscode.Uri: ${vscode.Uri},\n\t\t\tworkspace: ${vscode.workspace},\n\t\t\tdistGlob: ${distGlob.toString()},\n\t\t\thtmlGlob: ${htmlGlob.toString()},\n\t\t\tscriptGlob: ${scriptGlob.toString()}\n\t\t\t`);\n\t\t};\n\n\t\tvscode.window.showInformationMessage(`\n\t\t\trootPath: ${vscode.workspace.workspaceFolders[0].uri.toString()},\\n\n\t\t\tvscode URI parseTest: ${vscode.Uri.parse('file://'+ '/node_modules/@storybook/core/dist/public/index.html')},\\n\n\t\t\tvscode URI parsed w escape: ${vscode.Uri.parse('file://'+ '/node_modules/\\@storybook/core/dist/public/index.html')},\\n\n\t\t\tvscode URI file Test: ${vscode.Uri.file('node_modules/@storybook/core/dist/public/index.html')}\n\t\t\t`);\n\t\t\t\n\t\tconsole.log(`\n\t\trootPath: ${vscode.workspace.workspaceFolders[0]},\n\t\tvscode.Uri: ${vscode.Uri},\n\t\tworkspace: ${vscode.workspace},\n\t\tfileSys: ${vscode.Uri.file(path.join('/'))}`);\n });\n */","module.exports = require(\"child_process\");","module.exports = require(\"fs\");","module.exports = require(\"os\");","module.exports = require(\"path\");","module.exports = require(\"url\");","module.exports = require(\"vscode\");"],"sourceRoot":""} \ No newline at end of file diff --git a/src/extension.ts b/src/extension.ts index f46b856..72382b7 100644 --- a/src/extension.ts +++ b/src/extension.ts @@ -4,19 +4,10 @@ import * as path from 'path'; import * as fs from 'fs'; import * as ps from 'ps-node'; -let PORT = 6006; -const host = 'localhost'; - -// import * as express from 'express'; -// import { resolveCliPathFromVSCodeExecutablePath } from 'vscode-test'; -// const server = express(); - export function activate(context: vscode.ExtensionContext) { - // server.get('/', (req, res) => { - // vscode.window.showInformationMessage('Aesop server online'); - // res.end(); - // }); - // server.listen(PORT); + + let PORT = 6006; + const host = 'localhost'; //create disposable variable type, registers awaken command & opens webview let disposable = vscode.commands.registerCommand('extension.aesopAwaken', () => { @@ -26,7 +17,9 @@ export function activate(context: vscode.ExtensionContext) { //check first to ensure that Storybook has been depended into the current working directory fs.access(path.join(rootDir, '/node_modules/@storybook'), (err) => { + //if the filepath isn't found, show the user what Aesop is reading as the root path + if (err) { vscode.window.showErrorMessage(`Aesop could not find Storybook as a dependency in the active folder, ${rootDir}`); } else { @@ -38,8 +31,8 @@ export function activate(context: vscode.ExtensionContext) { if (err){ vscode.window.showErrorMessage(`Failed looking for running Node processes. Error: ${err}`); } else { + let foundSb = false; //if the process lookup was able to find running processes, iterate through to review them - //potential problem: we may also need to account for running processes given no port flag resultList.forEach((process) => { // ---> OUTPUT LOGGER <--- // @@ -50,86 +43,50 @@ export function activate(context: vscode.ExtensionContext) { //check if any running processes are using the start-storybook script if(process.arguments[0].includes('storybook')){ - + foundSb = true; //stretch goal: check for multiple instances of storybook and reconcile - - // ---> OUTPUT LOGGER <--- // - fs.appendFile(path.join(rootDir, 'YOLO.txt'), `This process matches for 'storybook'search string:\n - PID: ${process.pid}, COMMAND:${process.command}, ARGUMENTS: ${process.arguments}\n`, (err) => {console.log(err)}); - //if so, extract port number and use that value to populate the webview with that contents + const pFlagIndex = process.arguments.indexOf('-p'); if (pFlagIndex !== -1){ PORT = Number(process.arguments[pFlagIndex+1]); - } else { - //if no processes match 'storybook', we will have to spin up the storybook server - //starts by extracting the existing storybook script in the package.json - fs.readFile(path.join(rootDir, 'package.json'), (err, data) => { - if (err){ - vscode.window.showErrorMessage(`Does this root folder contain a "package.json" file?`); - } else { - //enter the package.JSON file and retrieve its contents as a string - let packageJSONText = data.toString(); - - // ---> OUTPUT LOGGER <--- // - fs.appendFile(path.join(rootDir, 'YOLO.txt'), `Here is the full contents of the package.json file from the user's workspace folder:\n${packageJSONText}\n`, (err) => {console.log(err)}); - - //find where the "storybook" script is defined - let targetScriptStartIndex = packageJSONText.indexOf(`\"storybook\"\:`)+12; - - //retrieve the value (i.e. the entire line of text) of the "storybook" script - let retrievedScript = packageJSONText.slice(targetScriptStartIndex, packageJSONText.indexOf(vscode.EndOfLine.toString())); - - // ---> OUTPUT LOGGER <--- // - fs.appendFile(path.join(rootDir, 'YOLO.txt'), `This is what our readFile function (line 72) returns when it attempts to retrieve (line 82) the "storybook" script from your app's package.json:\n${retrievedScript}\n`, (err) => {console.log(err)}); - - //iterate through that text string and parse out important flags - //it is more helpful to split it into an array separated by whitespace to grab these - let retrievedScriptAsArray = retrievedScript.split(' '); - for (let i = 0; i < retrievedScriptAsArray.length; i++){ - //add flags - if (retrievedScriptAsArray[i] === '-p'){ - PORT = Number(retrievedScriptAsArray[i+1]); - } - } - - /* - vscode.tasks.registerTaskProvider('runStorybook', { - provideTasks(token?: vscode.CancellationToken) { - return [ - new vscode.Task({type: 'runStorybook'}, vscode.TaskScope.Workspace, - "Aesop Chronicle", "aesop", new vscode.ShellExecution(`npm run storybook --ci`)) - ]; - }, - resolveTask(task: vscode.Task, token?: vscode.CancellationToken) { - return task; - } - }); - - //define the script text to execute to the virtual terminal instance - const bootScript = `storybook --ci`; - const bootStorybook = new vscode.ProcessExecution(bootScript, {cwd: rootDir}); - - //now create a virtual terminal and execute our special npm script for it - //this first requires creating an eventEmitter that will fire that script - const scriptEmitter = new vscode.EventEmitter(); - - //we also define a slave process Pseudoterminal (allowing Aesop to control the terminal) - const pty: vscode.Pseudoterminal = { - onDidWrite: scriptEmitter.event, - open: () => scriptEmitter.fire(bootScript), - close: () => {}, - handleInput: data => new vscode.ShellExecution(data) - }; - - //should this just be an active terminal/shellExecution? - const virtualTerminal = vscode.window.createTerminal({name: 'sb-runner', pty}); - */ - } - }) } + + // ---> OUTPUT LOGGER <--- // + fs.appendFile(path.join(rootDir, 'YOLO.txt'), `This process matches for 'storybook'search string:\n + PID: ${process.pid}, COMMAND:${process.command}, ARGUMENTS: ${process.arguments}\n`, (err) => {console.log(err)}); + } }) + + if (foundSb === false){ + //if no processes match 'storybook', we will have to spin up the storybook server + //starts by extracting the existing storybook script in the package.json + fs.readFile(path.join(rootDir, 'package.json'), (err, data) => { + if (err){ + vscode.window.showErrorMessage(`Does this root folder contain a "package.json" file?`); + } else { + //enter the package.JSON file and retrieve its contents as a string + let packageJSONText = JSON.parse(data.toString()); + let storybookScript = packageJSONText.scripts.storybook; + + // ---> OUTPUT LOGGER <--- // + fs.appendFile(path.join(rootDir, 'YOLO.txt'), `Here is the JSON parsed version:\n + ${packageJSONText.scripts}\n + ${storybookScript}`, (err) => {console.log(err)}); + + //iterate through that text string and parse out important flags + //it is more helpful to split it into an array separated by whitespace to grab these + let retrievedScriptArray = storybookScript.split(' '); + for (let i = 0; i < retrievedScriptArray.length; i++){ + //add flags + if (retrievedScriptArray[i] === '-p'){ + PORT = parseInt(retrievedScriptArray[i+1]); + } + } + } + }) + } } }) } @@ -180,6 +137,39 @@ to-do: figure out how to use a tsx rule in webpack to execute scripts signal babel to interpret this block as tsx, e.g. something like: //@tsx babel// + + + vscode.tasks.registerTaskProvider('runStorybook', { + provideTasks(token?: vscode.CancellationToken) { + return [ + new vscode.Task({type: 'runStorybook'}, vscode.TaskScope.Workspace, + "Aesop Chronicle", "aesop", new vscode.ShellExecution(`npm run storybook --ci`)) + ]; + }, + resolveTask(task: vscode.Task, token?: vscode.CancellationToken) { + return task; + } + }); + + //define the script text to execute to the virtual terminal instance + const bootScript = `storybook --ci`; + const bootStorybook = new vscode.ProcessExecution(bootScript, {cwd: rootDir}); + + //now create a virtual terminal and execute our special npm script for it + //this first requires creating an eventEmitter that will fire that script + const scriptEmitter = new vscode.EventEmitter(); + + //we also define a slave process Pseudoterminal (allowing Aesop to control the terminal) + const pty: vscode.Pseudoterminal = { + onDidWrite: scriptEmitter.event, + open: () => scriptEmitter.fire(bootScript), + close: () => {}, + handleInput: data => new vscode.ShellExecution(data) + }; + + //should this just be an active terminal/shellExecution? + const virtualTerminal = vscode.window.createTerminal({name: 'sb-runner', pty}); + //THIS WORKS, but we have no access to the DOM inside our webview// //now let's read SB's outputted index.html file, and parse out what we need fs.readFile(path.join(rootDir, '/node_modules/@storybook/core/dist/public/index.html'), (err, data) => { From 8fd8d2300b6c0e70e0a00cda4fb2984e2e5bb606 Mon Sep 17 00:00:00 2001 From: Keith Cagney Date: Thu, 2 Jan 2020 14:02:07 -0500 Subject: [PATCH 2/3] Attempting to debug webview error, adding control flow logic and Boolean variable checks to reduce nested operations --- dist/extension.js | 135 ++++++++++++++++++----------------- dist/extension.js.map | 2 +- src/extension.ts | 159 ++++++++++++++++++++++-------------------- 3 files changed, 157 insertions(+), 139 deletions(-) diff --git a/dist/extension.js b/dist/extension.js index 91f983c..d16c489 100644 --- a/dist/extension.js +++ b/dist/extension.js @@ -1032,6 +1032,8 @@ const ps = __webpack_require__(/*! ps-node */ "./node_modules/ps-node/index.js") function activate(context) { let PORT = 6006; const host = 'localhost'; + let dependencyFound = false; + let foundSb = false; //create disposable variable type, registers awaken command & opens webview let disposable = vscode.commands.registerCommand('extension.aesopAwaken', () => { //define a path to the root working directory of the user @@ -1043,79 +1045,83 @@ function activate(context) { vscode.window.showErrorMessage(`Aesop could not find Storybook as a dependency in the active folder, ${rootDir}`); } else { - //check to see if a storybook node process is already running - ps.lookup({ - command: 'node', - psargs: 'ux' - }, (err, resultList) => { - if (err) { - vscode.window.showErrorMessage(`Failed looking for running Node processes. Error: ${err}`); - } - else { - let foundSb = false; - //if the process lookup was able to find running processes, iterate through to review them - resultList.forEach((process) => { - // ---> OUTPUT LOGGER <--- // - fs.writeFile(path.join(rootDir, 'YOLO.txt'), `Here is the JSON-stringified version of a process:\n${JSON.stringify(process)}\n`, (err) => { console.log(`Couldn't output process information to YOLO.txt: ${err}`); }); - vscode.window.showInformationMessage('Check YOLO.txt for output information'); - //check if any running processes are using the start-storybook script - if (process.arguments[0].includes('storybook')) { - foundSb = true; - //stretch goal: check for multiple instances of storybook and reconcile - //if so, extract port number and use that value to populate the webview with that contents - const pFlagIndex = process.arguments.indexOf('-p'); - if (pFlagIndex !== -1) { - PORT = Number(process.arguments[pFlagIndex + 1]); - } - // ---> OUTPUT LOGGER <--- // - fs.appendFile(path.join(rootDir, 'YOLO.txt'), `This process matches for 'storybook'search string:\n - PID: ${process.pid}, COMMAND:${process.command}, ARGUMENTS: ${process.arguments}\n`, (err) => { console.log(err); }); + dependencyFound = true; + } + }); + if (dependencyFound === true && foundSb === false) { + //check to see if a storybook node process is already running + ps.lookup({ + command: 'node', + psargs: 'ux' + }, (err, resultList) => { + if (err) { + vscode.window.showErrorMessage(`Failed looking for running Node processes. Error: ${err}`); + } + else { + //if the process lookup was able to find running processes, iterate through to review them + resultList.forEach((process) => { + // ---> OUTPUT LOGGER <--- // + fs.writeFile(path.join(rootDir, 'YOLO.txt'), `YOLO, fam:\n\n\n\n`, (err) => { console.log(`Couldn't output process information to YOLO.txt: ${err}`); }); + vscode.window.showInformationMessage('Check YOLO.txt for output information'); + //check if any running processes are using the start-storybook script + if (process.arguments[0].includes('storybook')) { + foundSb = true; + //stretch goal: check for multiple instances of storybook and reconcile + //if so, extract port number and use that value to populate the webview with that contents + const pFlagIndex = process.arguments.indexOf('-p'); + if (pFlagIndex !== -1) { + PORT = Number(process.arguments[pFlagIndex + 1]); } - }); - if (foundSb === false) { - //if no processes match 'storybook', we will have to spin up the storybook server - //starts by extracting the existing storybook script in the package.json - fs.readFile(path.join(rootDir, 'package.json'), (err, data) => { - if (err) { - vscode.window.showErrorMessage(`Does this root folder contain a "package.json" file?`); - } - else { - //enter the package.JSON file and retrieve its contents as a string - let packageJSONText = JSON.parse(data.toString()); - let storybookScript = packageJSONText.scripts.storybook; - // // ---> OUTPUT LOGGER <--- // - // fs.appendFile(path.join(rootDir, 'YOLO.txt'), `Here is the JSON parsed version:\n - // ${packageJSONText.scripts}\n - // ${packageJSONText.scripts.storybook}`, (err) => {console.log(err)}); - // // ---> OUTPUT LOGGER <--- // - // fs.appendFile(path.join(rootDir, 'YOLO.txt'), `Here is the full contents of the package.json file from the user's workspace folder:\n${packageJSONText}\n`, (err) => {console.log(err)}); - // // ---> OUTPUT LOGGER <--- // - // fs.appendFile(path.join(rootDir, 'YOLO.txt'), `This is what our readFile function (line 72) returns when it attempts to retrieve (line 82) the "storybook" script from your app's package.json:\n${retrievedScript}\n`, (err) => {console.log(err)}); - //iterate through that text string and parse out important flags - //it is more helpful to split it into an array separated by whitespace to grab these - let retrievedScriptArray = storybookScript.split(' '); - for (let i = 0; i < retrievedScriptArray.length; i++) { - //add flags - if (retrievedScriptArray[i] === '-p') { - PORT = parseInt(retrievedScriptArray[i + 1]); - } - } - } - }); + // ---> OUTPUT LOGGER <--- // + fs.appendFile(path.join(rootDir, 'YOLO.txt'), `This process matches for 'storybook' search string:\n\n + PID: ${process.pid}, COMMAND:${process.command}, ARGUMENTS: ${process.arguments}\n\nPORT has been assigned to: ${PORT}`, (err) => { console.log(err); }); + } + }); + } + }); + } + ; + if (dependencyFound === true && foundSb === false) { + //if no processes match 'storybook', we will have to spin up the storybook server + //starts by extracting the existing storybook script in the package.json + fs.readFile(path.join(rootDir, 'package.json'), (err, data) => { + if (err) { + vscode.window.showErrorMessage(`Does this root folder contain a "package.json" file?`); + } + else { + //enter the package.JSON file and retrieve its contents as a string + let packageJSON = JSON.parse(data.toString()); + let storybookScript = packageJSON.scripts.storybook; + // // ---> OUTPUT LOGGER <--- // + // fs.appendFile(path.join(rootDir, 'YOLO.txt'), `Here is the JSON parsed version:\n + // ${packageJSON.scripts}\n + // ${storybookScript}`, (err) => {console.log(err)}); + //iterate through that text string and parse out important flags + //it is more helpful to split it into an array separated by whitespace to grab these + let retrievedScriptArray = storybookScript.split(' '); + for (let i = 0; i < retrievedScriptArray.length; i++) { + //add flags + if (retrievedScriptArray[i] === '-p') { + PORT = parseInt(retrievedScriptArray[i + 1]); } } - }); - } - }); + } + }); + //execute Ola's logic to launch the child process, passing rootDir as an options arg + } //set the extension context equal to "aesop is running" // vscode.commands.executeCommand("setContext", "is-running-aesop", true); //still inside our disposable variable, let's create the webview panel const panel = vscode.window.createWebviewPanel('aesop-sb', 'Aesop', vscode.ViewColumn.Two, { enableCommandUris: true, enableScripts: true, + portMapping: [ + { webviewPort: PORT, extensionHostPort: PORT } + ] }); panel.webview.html = - ` + ` + @@ -1123,9 +1129,10 @@ function activate(context) { Aesop - - `; + + `; }); context.subscriptions.push(disposable); } diff --git a/dist/extension.js.map b/dist/extension.js.map index 75c9805..ba2b779 100644 --- a/dist/extension.js.map +++ b/dist/extension.js.map @@ -1 +1 @@ -{"version":3,"sources":["../webpack/bootstrap",".././node_modules/connected-domain/index.js",".././node_modules/connected-domain/lib/connected-domain.js",".././node_modules/ps-node/index.js",".././node_modules/ps-node/lib/index.js",".././node_modules/table-parser/index.js",".././node_modules/table-parser/lib/index.js",".././src/extension.ts","../external \"child_process\"","../external \"fs\"","../external \"os\"","../external \"path\"","../external \"url\"","../external \"vscode\""],"names":[],"mappings":";;QAAA;QACA;;QAEA;QACA;;QAEA;QACA;QACA;QACA;QACA;QACA;QACA;QACA;QACA;QACA;;QAEA;QACA;;QAEA;QACA;;QAEA;QACA;QACA;;;QAGA;QACA;;QAEA;QACA;;QAEA;QACA;QACA;QACA,0CAA0C,gCAAgC;QAC1E;QACA;;QAEA;QACA;QACA;QACA,wDAAwD,kBAAkB;QAC1E;QACA,iDAAiD,cAAc;QAC/D;;QAEA;QACA;QACA;QACA;QACA;QACA;QACA;QACA;QACA;QACA;QACA;QACA,yCAAyC,iCAAiC;QAC1E,gHAAgH,mBAAmB,EAAE;QACrI;QACA;;QAEA;QACA;QACA;QACA,2BAA2B,0BAA0B,EAAE;QACvD,iCAAiC,eAAe;QAChD;QACA;QACA;;QAEA;QACA,sDAAsD,+DAA+D;;QAErH;QACA;;;QAGA;QACA;;;;;;;;;;;;AClFA,iBAAiB,mBAAO,EAAE,uFAAwB,G;;;;;;;;;;;ACAlD;AACA;AACA;;AAEA;AACA,WAAW,MAAM;AACjB,WAAW,SAAS;AACpB,WAAW,QAAQ;AACnB,YAAY,OAAO,GAAG,YAAY,2BAA2B,aAAa,sBAAsB,EAAE,qCAAqC;AACvI;AACA;;AAEA;;AAEA;AACA;AACA;;AAEA;AACA;AACA;;AAEA;AACA;;AAEA;AACA;AACA;AACA;;AAEA;;AAEA;;AAEA;;AAEA;AACA;;AAEA;AACA;AACA;;AAEA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;;AAEA;AACA;;AAEA;;AAEA;;AAEA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,iBAAiB;;AAEjB;AACA;AACA;AACA;AACA;AACA;AACA;AACA,SAAS;AACT,KAAK;;AAEL;AACA;AACA;AACA;AACA,6BAA6B;AAC7B;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;;AAEA;AACA;AACA;AACA;;AAEA;AACA;;;AAGA;;AAEA;AACA;AACA;AACA;;AAEA;;AAEA;AACA;AACA;;AAEA;AACA;AACA;;AAEA;AACA;AACA;;AAEA;AACA;AACA;AACA,SAAS;;AAET;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA,wBAAwB;AACxB;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;;AAEA;;AAEA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;;AAEA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;;AAEA;AACA;;AAEA;;AAEA;AACA;AACA;AACA,aAAa;;AAEb;;AAEA;AACA;AACA;AACA;;AAEA;AACA,E;;;;;;;;;;;AC/PA,iBAAiB,mBAAO,CAAC,kDAAO;;;;;;;;;;;;ACAhC,mBAAmB,mBAAO,CAAC,oCAAe;AAC1C;AACA,kBAAkB,mBAAO,CAAC,0DAAc;AACxC;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,gBAAgB,mBAAO,CAAC,cAAI;;AAE5B;AACA;AACA,UAAU;AACV,WAAW,SAAS;AACpB,WAAW,SAAS;AACpB,WAAW,YAAY;AACvB,WAAW,SAAS;AACpB;;AAEA;AACA;;AAEA;AACA;AACA;;AAEA;AACA;AACA;;AAEA;AACA;AACA,KAAK;;AAEL;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA,KAAK;;AAEL;;AAEA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA,OAAO;;AAEP;AACA;AACA;;AAEA;AACA,KAAK;;AAEL;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA,KAAK;;AAEL;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA,KAAK;;AAEL;AACA;AACA;AACA;AACA;AACA;AACA;AACA,KAAK;AACL;AACA;;AAEA;AACA;AACA;AACA,WAAW,gBAAgB;AAC3B,WAAW,OAAO;AAClB,WAAW,OAAO;AAClB,WAAW,aAAa;AACxB,WAAW,SAAS;AACpB,WAAW,YAAY;AACvB,WAAW,SAAS;AACpB,YAAY;AACZ;;AAEA;;AAEA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA,KAAK;;AAEL;;;AAGA;AACA;AACA;;AAEA;AACA;AACA;;AAEA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;;AAEA;AACA;AACA;;AAEA;AACA;AACA;;AAEA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA,OAAO;;AAEP;AACA;AACA,GAAG;AACH;;AAEA;AACA;AACA;AACA,WAAW,cAAc;AACzB,WAAW,OAAO;AAClB,WAAW,OAAO;AAClB;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;;AAEA;;AAEA;AACA;AACA;;AAEA;AACA;AACA,GAAG;AACH;AACA;;AAEA;AACA;AACA;;AAEA;AACA,oBAAoB,WAAW;AAC/B;;AAEA;AACA;AACA;AACA,OAAO;AACP;AACA;AACA,OAAO;AACP;AACA;AACA;AACA;AACA,SAAS;AACT;AACA;AACA;AACA,KAAK;AACL;;AAEA;;AAEA;AACA;AACA;AACA,GAAG;AACH;;AAEA;AACA;AACA,WAAW,OAAO;AAClB;;AAEA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA,YAAY;AACZ;;AAEA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;;AAEA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA,OAAO;AACP;AACA,GAAG;;AAEH;AACA;;;;;;;;;;;;ACpSA,iBAAiB,mBAAO,EAAE,6DAAa,G;;;;;;;;;;;ACAvC;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,sBAAsB,mBAAO,CAAC,kEAAkB;AAChD;;AAEA;AACA;AACA;AACA,aAAa;AACb;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA,GAAG;;AAEH;AACA;AACA;;AAEA;AACA;AACA;;AAEA;AACA;;AAEA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,OAAO;AACP;AACA;AACA;AACA;AACA,GAAG;;AAEH;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,GAAG;;AAEH;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,GAAG;;AAEH;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;;AAEA;;AAEA;AACA;AACA;AACA;AACA;AACA,OAAO;;AAEP;AACA;AACA;AACA;AACA;AACA;AACA,SAAS;AACT;AACA;AACA,GAAG;;AAEH;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;;AAEA;AACA;;AAEA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;;AAEA;;AAEA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;;AAEA;AACA,GAAG;;AAEH;AACA;;AAEA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA,GAAG;;AAEH;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA,aAAa;AACb;AACA;AACA;AACA;AACA,yCAAyC;AACzC;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;;AAEA;AACA;;AAEA;;AAEA;;AAEA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;A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","file":"extension.js","sourcesContent":[" \t// The module cache\n \tvar installedModules = {};\n\n \t// The require function\n \tfunction __webpack_require__(moduleId) {\n\n \t\t// Check if module is in cache\n \t\tif(installedModules[moduleId]) {\n \t\t\treturn installedModules[moduleId].exports;\n \t\t}\n \t\t// Create a new module (and put it into the cache)\n \t\tvar module = installedModules[moduleId] = {\n \t\t\ti: moduleId,\n \t\t\tl: false,\n \t\t\texports: {}\n \t\t};\n\n \t\t// Execute the module function\n \t\tmodules[moduleId].call(module.exports, module, module.exports, __webpack_require__);\n\n \t\t// Flag the module as loaded\n \t\tmodule.l = true;\n\n \t\t// Return the exports of the module\n \t\treturn module.exports;\n \t}\n\n\n \t// expose the modules object (__webpack_modules__)\n \t__webpack_require__.m = modules;\n\n \t// expose the module cache\n \t__webpack_require__.c = installedModules;\n\n \t// define getter function for harmony exports\n \t__webpack_require__.d = function(exports, name, getter) {\n \t\tif(!__webpack_require__.o(exports, name)) {\n \t\t\tObject.defineProperty(exports, name, { enumerable: true, get: getter });\n \t\t}\n \t};\n\n \t// define __esModule on exports\n \t__webpack_require__.r = function(exports) {\n \t\tif(typeof Symbol !== 'undefined' && Symbol.toStringTag) {\n \t\t\tObject.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });\n \t\t}\n \t\tObject.defineProperty(exports, '__esModule', { value: true });\n \t};\n\n \t// create a fake namespace object\n \t// mode & 1: value is a module id, require it\n \t// mode & 2: merge all properties of value into the ns\n \t// mode & 4: return value when already ns object\n \t// mode & 8|1: behave like require\n \t__webpack_require__.t = function(value, mode) {\n \t\tif(mode & 1) value = __webpack_require__(value);\n \t\tif(mode & 8) return value;\n \t\tif((mode & 4) && typeof value === 'object' && value && value.__esModule) return value;\n \t\tvar ns = Object.create(null);\n \t\t__webpack_require__.r(ns);\n \t\tObject.defineProperty(ns, 'default', { enumerable: true, value: value });\n \t\tif(mode & 2 && typeof value != 'string') for(var key in value) __webpack_require__.d(ns, key, function(key) { return value[key]; }.bind(null, key));\n \t\treturn ns;\n \t};\n\n \t// getDefaultExport function for compatibility with non-harmony modules\n \t__webpack_require__.n = function(module) {\n \t\tvar getter = module && module.__esModule ?\n \t\t\tfunction getDefault() { return module['default']; } :\n \t\t\tfunction getModuleExports() { return module; };\n \t\t__webpack_require__.d(getter, 'a', getter);\n \t\treturn getter;\n \t};\n\n \t// Object.prototype.hasOwnProperty.call\n \t__webpack_require__.o = function(object, property) { return Object.prototype.hasOwnProperty.call(object, property); };\n\n \t// __webpack_public_path__\n \t__webpack_require__.p = \"\";\n\n\n \t// Load entry module and return exports\n \treturn __webpack_require__(__webpack_require__.s = \"./src/extension.ts\");\n","module.exports = require( './lib/connected-domain' );","/**\n * calculate all the connected domains based on the given two-dimensional array\n */\n\n/**\n * @param {Array} tdArray\n * @param {Function} indicator It receive the raw point data as the first parameter and decide what kind of domain the point belongs to, it should return a string as a domain identifier.\n * @param {Boolean} hardlink If use hard link. Default to false.\n * @return {Object} [{ bounding: { w: 12, h: 19, x: 0, y: 1 }, points: [ { x: 1, y: 2, point: {} } ], identifier: 'blue', domainId: 1 } ]\n */\nmodule.exports = function( tdArray, indicator, hardlink ){\n\n hardlink = hardlink || false;\n\n if( !tdArray ){\n throw new Error( 'tdArray must be provided' );\n }\n\n if( !indicator ){\n throw new Error( 'indicator must be provided' );\n }\n\n // clone 一份数据,因为需要对饮用进行修改,方便执行\n tdArray = JSON.parse( JSON.stringify( tdArray ) );\n\n // Result\n var domains = {};\n var domainUUID = 0;\n var pointsHash = {};\n\n // 遍历数组,划分domain\n\n tdArray.forEach(function( row, y ){\n\n row.forEach(function( colItem, x ){\n\n // get the current point identifier.\n var identifier = indicator( colItem, x, y );\n\n // get neighbours\n // Except for Undefined every data type is valid.\n var neighbours = [];\n\n // top neighbour\n if( tdArray[ y - 1 ] && tdArray[ y - 1 ][ x ] !== undefined ){\n neighbours.push( pointsHash[ x + '_' + ( y - 1 ) ] );\n }\n\n // left neighbour\n if( row[ x - 1 ] !== undefined ){\n neighbours.push( pointsHash[ ( x - 1 ) + '_' + y ] );\n }\n\n // soft link will treat corner link as domain link.\n if( !hardlink ){\n // top left neighbour\n if( tdArray[ y - 1 ] && tdArray[ y - 1 ][ x - 1 ] !== undefined ){\n neighbours.push( pointsHash[ ( x - 1 ) + '_' + ( y - 1 ) ] );\n }\n\n // top right neighbour\n if( tdArray[ y - 1 ] && tdArray[ y - 1 ][ x + 1 ] !== undefined ){\n neighbours.push( pointsHash[ ( x + 1 ) + '_' + ( y - 1 ) ] );\n }\n }\n\n if( neighbours.length ){\n var matched = false;\n\n neighbours.forEach(function( neighbour ){\n\n if( neighbour.identifier == identifier ){\n\n // If the neighbour is the first neighbour has the same identifier\n if( !matched ){\n addPointToDomain( colItem, x, y, neighbour.domainId );\n matched = true;\n }\n\n // If more than one neighbour matched, check if these neighbours belong to the same domain\n // If not, merge these domains since they connects to each other.\n else {\n var colItemPoint = pointsHash[ x + '_' + y ];\n if( neighbour.domainId != colItemPoint.domainId ){\n mergeDomains( neighbour.domainId, colItemPoint.domainId );\n }\n }\n }\n });\n\n if( !matched ){\n addNewDomain( colItem, x, y, identifier );\n }\n }\n else {\n addNewDomain( colItem, x, y, identifier );\n }\n });\n });\n\n // some summary\n var result = {\n domains: [],\n totalDomains: 0,\n groupByIdentifier: {},\n totalIdentifiers: 0\n };\n\n var domainId = null;\n var identifier = null;\n var domain = null;\n for( domainId in domains ){\n domain = domains[ domainId ];\n domain.bounding = calculateBounding( domain.points );\n identifier = domain.identifier;\n\n result.domains.push( domain );\n result.totalDomains++;\n\n if( !( identifier in result.groupByIdentifier ) ){\n result.groupByIdentifier[ identifier ] = [];\n result.totalIdentifiers++;\n }\n\n result.groupByIdentifier[ identifier ].push( domain );\n }\n\n\n function calculateBounding( points ){\n\n var minX = null;\n var minY = null;\n var maxX = null;\n var maxY = null;\n\n points.forEach(function( point ){\n\n if( minX === null || point.x < minX ){\n minX = point.x;\n }\n\n if( minY === null || point.y < minY ){\n minY = point.y;\n }\n\n if( maxX === null || point.x > maxX ){\n maxX = point.x;\n }\n\n if( maxY === null || point.y > maxY ){\n maxY = point.y;\n }\n });\n\n var w = maxX - minX;\n var h = maxY - minY;\n\n return {\n x: minX,\n y: minY,\n w: w,\n h: h\n };\n }\n\n /**\n *\n * @param point\n * @param x\n * @param y\n * @param identifier\n */\n function addNewDomain( point, x, y, identifier ){\n\n var newDomain = {\n identifier: identifier,\n domainId: ++domainUUID,\n bounding: {},\n points: []\n };\n\n var newPoint = {\n value: point,\n x: x,\n y: y,\n identifier: identifier,\n domainId: newDomain.domainId\n };\n\n pointsHash[ x + '_' + y ] = {\n value: point,\n identifier: identifier,\n domainId: newDomain.domainId\n };\n\n newDomain.points.push( newPoint );\n\n domains[ newDomain.domainId ] = newDomain;\n }\n\n /**\n * add a point to a existing domain, and attach properties domainId and identifier to point.\n * @param point\n * @param x\n * @param y\n * @param domainId\n */\n function addPointToDomain( point, x, y, domainId ){\n\n var domain = domains[ domainId ];\n var newPoint = {\n value: point,\n x: x,\n y: y,\n identifier: domain.identifier,\n domainId: domainId\n };\n\n pointsHash[ x + '_' + y ] = {\n value: point,\n identifier: domain.identifier,\n domainId: domainId\n };\n\n domain.points.push( newPoint );\n }\n\n /**\n * 将 domainB 合并到 domainA\n * @param domainAId\n * @param domainBId\n */\n function mergeDomains( domainAId, domainBId ){\n\n var domainA = domains[ domainAId ];\n var domainB = domains[ domainBId ];\n\n if( domainA.identifier == domainB.identifier ){\n // 更新 domainB 的domainId\n\n domainB.domainId = domainA.domainId;\n\n domainB.points.forEach(function( point ){\n point.domainId = domainA.domainId;\n pointsHash[ point.x + '_' + point.y ].domainId = domainA.domainId;\n });\n\n domainA.points = domainA.points.concat( domainB.points );\n\n // 删除domainB\n delete domains[ domainBId ];\n }\n }\n\n return result;\n};","module.exports = require('./lib');\n","var ChildProcess = require('child_process');\nvar IS_WIN = process.platform === 'win32';\nvar TableParser = require('table-parser');\n/**\n * End of line.\n * Basically, the EOL should be:\n * - windows: \\r\\n\n * - *nix: \\n\n * But i'm trying to get every possibilities covered.\n */\nvar EOL = /(\\r\\n)|(\\n\\r)|\\n|\\r/;\nvar SystemEOL = require('os').EOL;\n\n/**\n * Execute child process\n * @type {Function}\n * @param {String[]} args\n * @param {Function} callback\n * @param {Object=null} callback.err\n * @param {Object[]} callback.stdout\n */\n\nvar Exec = module.exports = exports = function (args, callback) {\n var spawn = ChildProcess.spawn;\n\n // on windows, if use ChildProcess.exec(`wmic process get`), the stdout will gives you nothing\n // that's why I use `cmd` instead\n if (IS_WIN) {\n\n var CMD = spawn('cmd');\n var stdout = '';\n var stderr = null;\n\n CMD.stdout.on('data', function (data) {\n stdout += data.toString();\n });\n\n CMD.stderr.on('data', function (data) {\n\n if (stderr === null) {\n stderr = data.toString();\n }\n else {\n stderr += data.toString();\n }\n });\n\n CMD.on('exit', function () {\n\n var beginRow;\n stdout = stdout.split(EOL);\n\n // Find the line index for the titles\n stdout.forEach(function (out, index) {\n if (out && typeof beginRow == 'undefined' && out.indexOf('CommandLine') === 0) {\n beginRow = index;\n }\n });\n\n // get rid of the start (copyright) and the end (current pwd)\n stdout.splice(stdout.length - 1, 1);\n stdout.splice(0, beginRow);\n\n callback(stderr, stdout.join(SystemEOL) || false);\n });\n\n CMD.stdin.write('wmic process get ProcessId,ParentProcessId,CommandLine \\n');\n CMD.stdin.end();\n }\n else {\n if (typeof args === 'string') {\n args = args.split(/\\s+/);\n }\n const child = spawn('ps', args);\n var stdout = '';\n var stderr = null;\n\n child.stdout.on('data', function (data) {\n stdout += data.toString();\n });\n\n child.stderr.on('data', function (data) {\n\n if (stderr === null) {\n stderr = data.toString();\n }\n else {\n stderr += data.toString();\n }\n });\n\n child.on('exit', function () {\n if (stderr) {\n return callback(stderr.toString());\n }\n else {\n callback(null, stdout || false);\n }\n });\n }\n};\n\n/**\n * Query Process: Focus on pid & cmd\n * @param query\n * @param {String|String[]} query.pid\n * @param {String} query.command RegExp String\n * @param {String} query.arguments RegExp String\n * @param {String|array} query.psargs\n * @param {Function} callback\n * @param {Object=null} callback.err\n * @param {Object[]} callback.processList\n * @return {Object}\n */\n\nexports.lookup = function (query, callback) {\n\n /**\n * add 'lx' as default ps arguments, since the default ps output in linux like \"ubuntu\", wont include command arguments\n */\n var exeArgs = query.psargs || ['lx'];\n var filter = {};\n var idList;\n\n // Lookup by PID\n if (query.pid) {\n\n if (Array.isArray(query.pid)) {\n idList = query.pid;\n }\n else {\n idList = [query.pid];\n }\n\n // Cast all PIDs as Strings\n idList = idList.map(function (v) {\n return String(v);\n });\n\n }\n\n\n if (query.command) {\n filter['command'] = new RegExp(query.command, 'i');\n }\n\n if (query.arguments) {\n filter['arguments'] = new RegExp(query.arguments, 'i');\n }\n\n if (query.ppid) {\n filter['ppid'] = new RegExp(query.ppid);\n }\n\n return Exec(exeArgs, function (err, output) {\n if (err) {\n return callback(err);\n }\n else {\n var processList = parseGrid(output);\n var resultList = [];\n\n processList.forEach(function (p) {\n\n var flt;\n var type;\n var result = true;\n\n if (idList && idList.indexOf(String(p.pid)) < 0) {\n return;\n }\n\n for (type in filter) {\n flt = filter[type];\n result = flt.test(p[type]) ? result : false;\n }\n\n if (result) {\n resultList.push(p);\n }\n });\n\n callback(null, resultList);\n }\n });\n};\n\n/**\n * Kill process\n * @param pid\n * @param {Object|String} signal\n * @param {String} signal.signal\n * @param {number} signal.timeout\n * @param next\n */\n\nexports.kill = function( pid, signal, next ){\n //opts are optional\n if(arguments.length == 2 && typeof signal == 'function'){\n next = signal;\n signal = undefined;\n }\n\n var checkTimeoutSeconds = (signal && signal.timeout) || 30;\n\n if (typeof signal === 'object') {\n signal = signal.signal;\n }\n\n try {\n process.kill(pid, signal);\n } catch(e) {\n return next && next(e);\n }\n\n var checkConfident = 0;\n var checkTimeoutTimer = null;\n var checkIsTimeout = false;\n\n function checkKilled(finishCallback) {\n exports.lookup({ pid: pid }, function(err, list) {\n if (checkIsTimeout) return;\n\n if (err) {\n clearTimeout(checkTimeoutTimer);\n finishCallback && finishCallback(err);\n } else if(list.length > 0) {\n checkConfident = (checkConfident - 1) || 0;\n checkKilled(finishCallback);\n } else {\n checkConfident++;\n if (checkConfident === 5) {\n clearTimeout(checkTimeoutTimer);\n finishCallback && finishCallback();\n } else {\n checkKilled(finishCallback);\n }\n }\n });\n }\n\n next && checkKilled(next);\n\n checkTimeoutTimer = next && setTimeout(function() {\n checkIsTimeout = true;\n next(new Error('Kill process timeout'));\n }, checkTimeoutSeconds * 1000);\n};\n\n/**\n * Parse the stdout into readable object.\n * @param {String} output\n */\n\nfunction parseGrid(output) {\n if (!output) {\n return [];\n }\n return formatOutput(TableParser.parse(output));\n}\n\n/**\n * format the structure, extract pid, command, arguments, ppid\n * @param data\n * @return {Array}\n */\n\nfunction formatOutput(data) {\n var formatedData = [];\n data.forEach(function (d) {\n var pid = ( d.PID && d.PID[0] ) || ( d.ProcessId && d.ProcessId[0] ) || undefined;\n var cmd = d.CMD || d.CommandLine || d.COMMAND || undefined;\n var ppid = ( d.PPID && d.PPID[0] ) || ( d.ParentProcessId && d.ParentProcessId[0] ) || undefined;\n\n if (pid && cmd) {\n var command = cmd[0];\n var args = '';\n\n if (cmd.length > 1) {\n args = cmd.slice(1);\n }\n\n formatedData.push({\n pid: pid,\n command: command,\n arguments: args,\n ppid: ppid\n });\n }\n });\n\n return formatedData;\n}\n","module.exports = require( './lib/index' );","/**\n *\n * 1, define the edge ( begin and end ) of every title field\n * 2, parse all the lines except the title line, get all the connected-domains\n * 3, group all the connected-domains vertically overlapped.\n * 4, a domain group belongs to a title field if they vertically overlapped\n * 5, calculate all the edge info through the group domain and title field relations.\n */\nvar ConnectedDomain = require('connected-domain');\nvar EMPTY_EX = /\\s/;\n\n/**\n * The output sting of cmd to parse\n * @param output\n * @returns {Array}\n */\nmodule.exports.parse = function (output) {\n\n // Split into lines\n // Basically, the EOL should be:\n // - windows: \\r\\n\n // - *nix: \\n\n // But i'm trying to get every possibilities covered.\n var linesTmp = output.split(/(\\r\\n)|(\\n\\r)|\\n|\\r/);\n\n // valid lines\n var lines = [];\n // title field info, mapped with filed name.\n var titleInfo = {};\n // the two dimensional array of the lines\n var twoDimArray = [];\n\n // get rid of all the empty lines.\n linesTmp.forEach(function (line) {\n if (line && line.trim()) {\n lines.push(line);\n }\n });\n\n // build title fields edge info\n // build two dimensional array for Connected-Domain to parse.\n lines.forEach(function (line, index) {\n\n // Treat the first line as the title fields line\n if (index == 0) {\n var fields = line.split(/\\s+/);\n\n // record the beginning and ending for each field\n fields.forEach(function (field, idx) {\n\n if (field) {\n var info = titleInfo[field] = {};\n var indexBegin = line.indexOf(field);\n var indexEnd = indexBegin + field.length;\n\n if (idx == 0) {\n info.titleBegin = 0;\n }\n else {\n info.titleBegin = indexBegin;\n }\n\n if (idx == fields.length - 1) {\n info.titleEnd = line.length - 1;\n }\n else {\n info.titleEnd = indexEnd;\n }\n }\n });\n }\n else {\n twoDimArray[index - 1] = line.split('');\n }\n });\n\n // In the connected-domain aspect of view, all the blanks are connected, and all the non-blanks are connected.\n var connectedDomains = ConnectedDomain(twoDimArray, function (value) {\n if (EMPTY_EX.test(value)) {\n return -1;\n }\n else {\n return 1;\n }\n }, true);\n\n // all the connected domains grouped if they are vertically overlapped.\n var valuesDomainsVerticalGroups = [];\n\n // sore the domain list make 'x' in ascending order, it will prevent the situation that:\n // 1, two domains are not overlapped, so two groups are created for them at first\n // 2, another domain is found overlapped with both of the domains at the first step.\n // 3, In this situation the three groups have to be merged, which is complicated to implement.\n //\n // If the list is sorted in this order, this situation can't happen, because:\n // - 1, If two non-overlapped domains A, B ( the \"x\" value of A less than B ) are found first.\n // - 2, Since the list is in 'x' ascending order, the 'x' values of the following domains must larger or equal to the \"x\" of B, which means they will never overlapped with domain A.\n // - 3, So this situation can't happen.\n connectedDomains.domains.sort(function (a, b) {\n return a.bounding.x - b.bounding.x;\n });\n\n // Group domains vertically overlapped.\n connectedDomains.domains.forEach(function (domain) {\n // only handle un-empty domain\n if (domain.identifier === 1) {\n var overlapped = false;\n\n // If overlapped\n valuesDomainsVerticalGroups.forEach(function (group) {\n var bounding = domain.bounding;\n var left = bounding.x;\n var right = bounding.x + bounding.w;\n\n if (overlap(left, right, group.begin, group.end)) {\n\n overlapped = true;\n group.domains.push(domain);\n group.begin = group.begin > left ? left : group.begin;\n group.end = group.end < right ? right : group.end;\n }\n });\n\n // If not overlapped with any group, then create a new group\n if (!overlapped) {\n valuesDomainsVerticalGroups.push({\n begin: domain.bounding.x,\n end: domain.bounding.x + domain.bounding.w,\n domains: [domain]\n });\n }\n }\n });\n\n // connect all the groups to the title fields\n valuesDomainsVerticalGroups.forEach(function (group) {\n var title = null;\n var info = null;\n var overlapped = false;\n\n var minimunLeftDistance = null;\n var nearestLeftTitle = null;\n var distance = null;\n\n for (title in titleInfo) {\n info = titleInfo[title];\n\n /**\n * The calculation below is to find the nearest left title field to the group, in case no overlapped title field found.\n */\n if (group.begin > info.titleBegin) {\n distance = group.begin - info.titleBegin;\n\n if (!nearestLeftTitle || ( distance < minimunLeftDistance )) {\n nearestLeftTitle = title;\n minimunLeftDistance = distance;\n }\n }\n\n if (overlap(group.begin, group.end, info.titleBegin, info.titleEnd)) {\n\n overlapped = true;\n info.titleBegin = info.titleBegin > group.begin ? group.begin : info.titleBegin;\n info.titleEnd = info.titleEnd < group.end ? group.end : info.titleEnd;\n }\n }\n\n // Groups not match any title field belongs to the nearest left title field\n if (!overlapped && nearestLeftTitle) {\n var nearestTitleField = titleInfo[nearestLeftTitle];\n nearestTitleField.titleBegin = nearestTitleField.titleBegin > group.begin ? group.begin : nearestTitleField.titleBegin;\n nearestTitleField.titleEnd = nearestTitleField.titleEnd < group.end ? group.end : nearestTitleField.titleEnd;\n\n }\n });\n\n // The final result\n var result = [];\n\n // Since we have got all the title bounding edges, we can split all the lines into values now\n lines.forEach(function (line, index) {\n // skip the first line\n if (index > 0) {\n\n var lineItem = {};\n var title = null;\n var info = null;\n var value = null;\n for (title in titleInfo) {\n info = titleInfo[title];\n value = line.substring(info.titleBegin, info.titleEnd + 1);\n lineItem[title] = splitValue(value.trim());\n }\n\n result.push(lineItem);\n }\n });\n\n return result;\n};\n\n/**\n * Test if two bounding overlapped vertically\n * @param begin1\n * @param end1\n * @param begin2\n * @param end2\n * @returns {boolean}\n */\nfunction overlap(begin1, end1, begin2, end2) {\n return ( begin1 > begin2 && begin1 < end2 ) || // 2--1--2--1 or 2--1--1--2\n ( end1 > begin2 && end1 < end2 ) || // 1--2--1--2 or 2--1--1--2\n ( begin1 <= begin2 && end1 >= end2 );// 21--12 or 1--2--2--1\n}\n\n/**\n * transform a string value into array. It's not just split(), but also to consider some chunk that wrapped with `\"`, like below:\n * \"C:\\Program Files\\Google\\Chrome\\Application\\chrome.exe\" --type=renderer --lang=zh-CN, `C:\\Program Files\\Google\\Chrome\\Application\\chrome.exe` should be treated as a whole,\n * also, be careful don't be mislead by format like `--name=\"neekey\"`, even more complicated: `--name=\"Neekey Ni\"`\n * so, `\"C:\\Program Files\\Internet Explorer\\iexplore.exe\" --name=\"Jack Neekey\"` should split into:\n * - C:\\Program Files\\Internet Explorer\\iexplore.exe // without `\"`\n * - --name=\"Jack Neekey\" // with `\"`\n */\nfunction splitValue(value) {\n\n var match = value.match(/\"/g);\n\n // If only one \" found, then just ignore it\n if (!match || match.length == 1) {\n return value.split(/\\s+/);\n }\n else {\n var result = [];\n var chunk = null;\n var ifInWrappedChunk = false;\n var ifInPureWrappedChunk = false;\n var quotaCount = 0;\n\n // If the match length is a even, than nothing special, if a odd, ignore the last one.\n var maxQuotaCount = match.length % 2 == 0 ? match.length : match.length - 1;\n\n var previousItem = null;\n var values = value.split('');\n\n values.forEach(function (item, index) {\n\n if (item !== ' ') {\n\n if (item === '\"') {\n // quota chunk begin\n if (ifInWrappedChunk === false && quotaCount <= maxQuotaCount) {\n ifInWrappedChunk = true;\n quotaCount++;\n\n // pure quota chunk begin\n if (previousItem === ' ' || previousItem === null) {\n ifInPureWrappedChunk = true;\n chunk = '';\n }\n // normal continue\n else {\n chunk += item;\n }\n }\n // quota chunk end\n else if (ifInWrappedChunk === true) {\n ifInWrappedChunk = false;\n quotaCount++;\n\n // pure quota chunk end\n if (ifInPureWrappedChunk === true) {\n ifInPureWrappedChunk = false;\n result.push(chunk);\n chunk = null;\n }\n // normal continue\n else {\n chunk += item;\n }\n }\n }\n // normal begin\n else if (ifInWrappedChunk === false && ( previousItem === ' ' || previousItem === null )) {\n chunk = item;\n }\n // normal or quota chunk continue.\n else {\n chunk += item;\n }\n }\n // quota chunk continue, in quota chunk, blank is valid.\n else if (ifInWrappedChunk) {\n chunk += item;\n }\n // if not in quota chunk, them a blank means an end. But make sure chunk is exist, cause that could be blanks at the beginning.\n else if (chunk !== null) {\n result.push(chunk);\n chunk = null;\n }\n\n previousItem = item;\n\n // If this is the last one, but chunk is not end\n if (index == ( values.length - 1 ) && chunk !== null) {\n result.push(chunk);\n chunk = null;\n }\n });\n\n return result;\n }\n}\n","import * as vscode from 'vscode';\nimport { fileURLToPath } from 'url';\nimport * as path from 'path';\nimport * as fs from 'fs';\nimport * as ps from 'ps-node';\n\nexport function activate(context: vscode.ExtensionContext) {\n\n\tlet PORT = 6006;\n\tconst host = 'localhost';\n\n //create disposable variable type, registers awaken command & opens webview\n\tlet disposable = vscode.commands.registerCommand('extension.aesopAwaken', () => {\n\n\t\t//define a path to the root working directory of the user\n\t\tconst rootDir = fileURLToPath(vscode.workspace.workspaceFolders[0].uri.toString(true));\n\n\t\t//check first to ensure that Storybook has been depended into the current working directory\n\t\tfs.access(path.join(rootDir, '/node_modules/@storybook'), (err) => {\n\n\t\t\t//if the filepath isn't found, show the user what Aesop is reading as the root path\n\n\t\t\tif (err) {\n\t\t\t\tvscode.window.showErrorMessage(`Aesop could not find Storybook as a dependency in the active folder, ${rootDir}`);\n\t\t\t}\telse {\n\t\t\t\t//check to see if a storybook node process is already running\n\t\t\t\tps.lookup({\n\t\t\t\t\tcommand: 'node',\n\t\t\t\t\tpsargs: 'ux'\n\t\t\t\t}, (err, resultList) => {\n\t\t\t\t\tif (err){\n\t\t\t\t\t\tvscode.window.showErrorMessage(`Failed looking for running Node processes. Error: ${err}`);\n\t\t\t\t\t} else {\n\t\t\t\t\t\tlet foundSb = false;\n\t\t\t\t\t\t//if the process lookup was able to find running processes, iterate through to review them\n\t\t\t\t\t\tresultList.forEach((process) => {\n\n\t\t\t\t\t\t\t// ---> OUTPUT LOGGER <--- //\n\t\t\t\t\t\t\tfs.writeFile(path.join(rootDir, 'YOLO.txt'),\n\t\t\t\t\t\t\t`Here is the JSON-stringified version of a process:\\n${JSON.stringify(process)}\\n`,\n\t\t\t\t\t\t\t(err) => {console.log(`Couldn't output process information to YOLO.txt: ${err}`)});\n\t\t\t\t\t\t\tvscode.window.showInformationMessage('Check YOLO.txt for output information');\n\n\t\t\t\t\t\t\t//check if any running processes are using the start-storybook script\n\t\t\t\t\t\t\tif(process.arguments[0].includes('storybook')){\n\t\t\t\t\t\t\t\tfoundSb = true;\n\t\t\t\t\t\t\t\t//stretch goal: check for multiple instances of storybook and reconcile\n\t\t\t\t\t\t\t\t//if so, extract port number and use that value to populate the webview with that contents\n\t\t\t\t\t\t\t\n\t\t\t\t\t\t\t\tconst pFlagIndex = process.arguments.indexOf('-p');\n\t\t\t\t\t\t\t\tif (pFlagIndex !== -1){\n\t\t\t\t\t\t\t\t\tPORT = Number(process.arguments[pFlagIndex+1]);\n\t\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\t\t// ---> OUTPUT LOGGER <--- //\n\t\t\t\t\t\t\t\tfs.appendFile(path.join(rootDir, 'YOLO.txt'), `This process matches for 'storybook'search string:\\n\n\t\t\t\t\t\t\t\tPID: ${process.pid}, COMMAND:${process.command}, ARGUMENTS: ${process.arguments}\\n`, (err) => {console.log(err)});\n\t\t\t\t\t\t\t\t\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t})\n\n\t\t\t\t\t\tif (foundSb === false){\n\t\t\t\t\t\t\t\t//if no processes match 'storybook', we will have to spin up the storybook server\n\t\t\t\t\t\t\t\t//starts by extracting the existing storybook script in the package.json\n\t\t\t\t\t\t\t\tfs.readFile(path.join(rootDir, 'package.json'), (err, data) => {\n\t\t\t\t\t\t\t\t\tif (err){\n\t\t\t\t\t\t\t\t\t\tvscode.window.showErrorMessage(`Does this root folder contain a \"package.json\" file?`);\n\t\t\t\t\t\t\t\t\t}\telse {\n\t\t\t\t\t\t\t\t\t\t//enter the package.JSON file and retrieve its contents as a string\n\t\t\t\t\t\t\t\t\t\tlet packageJSONText = JSON.parse(data.toString());\n\t\t\t\t\t\t\t\t\t\tlet storybookScript = packageJSONText.scripts.storybook;\n\n\t\t\t\t\t\t\t\t\t\t// // ---> OUTPUT LOGGER <--- //\n\t\t\t\t\t\t\t\t\t\t// fs.appendFile(path.join(rootDir, 'YOLO.txt'), `Here is the JSON parsed version:\\n\n\t\t\t\t\t\t\t\t\t\t// ${packageJSONText.scripts}\\n\n\t\t\t\t\t\t\t\t\t\t// ${packageJSONText.scripts.storybook}`, (err) => {console.log(err)});\n\n\t\t\t\t\t\t\t\t\t\t// // ---> OUTPUT LOGGER <--- //\n\t\t\t\t\t\t\t\t\t\t// fs.appendFile(path.join(rootDir, 'YOLO.txt'), `Here is the full contents of the package.json file from the user's workspace folder:\\n${packageJSONText}\\n`, (err) => {console.log(err)});\n\n\t\t\t\t\t\t\t\t\t\t// // ---> OUTPUT LOGGER <--- //\n\t\t\t\t\t\t\t\t\t\t// fs.appendFile(path.join(rootDir, 'YOLO.txt'), `This is what our readFile function (line 72) returns when it attempts to retrieve (line 82) the \"storybook\" script from your app's package.json:\\n${retrievedScript}\\n`, (err) => {console.log(err)});\n\n\t\t\t\t\t\t\t\t\t\t//iterate through that text string and parse out important flags\n\t\t\t\t\t\t\t\t\t\t//it is more helpful to split it into an array separated by whitespace to grab these\n\t\t\t\t\t\t\t\t\t\tlet retrievedScriptArray = storybookScript.split(' ');\n\t\t\t\t\t\t\t\t\t\tfor (let i = 0; i < retrievedScriptArray.length; i++){\n\t\t\t\t\t\t\t\t\t\t\t//add flags\n\t\t\t\t\t\t\t\t\t\t\tif (retrievedScriptArray[i] === '-p'){\n\t\t\t\t\t\t\t\t\t\t\t\tPORT = parseInt(retrievedScriptArray[i+1]);\n\t\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t})\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t})\n\t\t\t}\n\t\t})\n\n\t\t//set the extension context equal to \"aesop is running\"\n\t\t// vscode.commands.executeCommand(\"setContext\", \"is-running-aesop\", true);\n\n\t\t//still inside our disposable variable, let's create the webview panel\n\t\tconst panel : vscode.WebviewPanel = vscode.window.createWebviewPanel(\n\t\t\t'aesop-sb',\n\t\t\t'Aesop',\n\t\t\tvscode.ViewColumn.Two,\n\t\t\t{\n\t\t\t\tenableCommandUris: true,\n\t\t\t\tenableScripts: true,\n\t\t\t\t// portMapping: [\n\t\t\t\t// \t{ webviewPort: PORT, extensionHostPort: PORT}\n\t\t\t\t// ]\n\t\t\t}\n\t\t);\n\n\t\tpanel.webview.html =\n\t\t\t`\n\t\t\t\n\t\t\t\t\n\t\t\t\t\t\n\t\t\t\t\t\n\t\t\t\t\tAesop\n\t\t\t\t\n\t\t\t\t\n\t\t\t\t\t\n\t\t\t\t\n\t\t\t`\n\t})\n\n\tcontext.subscriptions.push(disposable);\n};\n\nexport function deactivate() {\n\t\n}\n\n/*\nto-do:\n\tfigure out how to iteratively call sb scripts within our webview\n\twebview messages / scripts to reload\n\tfigure out how to use a tsx rule in webpack to execute scripts\n\tsignal babel to interpret this block as tsx, e.g. something like: //@tsx babel//\n\n\n\t\n\t\t\t\t\t\tvscode.tasks.registerTaskProvider('runStorybook', {\n\t\t\t\t\t\t\t\t\t\t\t\tprovideTasks(token?: vscode.CancellationToken) {\n\t\t\t\t\t\t\t\t\t\t\t\t\t\treturn [\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tnew vscode.Task({type: 'runStorybook'}, vscode.TaskScope.Workspace,\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\"Aesop Chronicle\", \"aesop\", new vscode.ShellExecution(`npm run storybook --ci`))\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t];\n\t\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\tresolveTask(task: vscode.Task, token?: vscode.CancellationToken) {\n\t\t\t\t\t\t\t\t\t\t\t\t\t\treturn task;\n\t\t\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t\t\t});\n\n\t\t\t\t\t\t\t\t\t\t\t//define the script text to execute to the virtual terminal instance\n\t\t\t\t\t\t\t\t\t\t\tconst bootScript = `storybook --ci`;\n\t\t\t\t\t\t\t\t\t\t\tconst bootStorybook = new vscode.ProcessExecution(bootScript, {cwd: rootDir});\n\n\t\t\t\t\t\t\t\t\t\t\t//now create a virtual terminal and execute our special npm script for it\n\t\t\t\t\t\t\t\t\t\t\t//this first requires creating an eventEmitter that will fire that script\n\t\t\t\t\t\t\t\t\t\t\tconst scriptEmitter = new vscode.EventEmitter();\n\t\t\t\t\t\t\t\n\t\t\t\t\t\t\t\t\t\t\t//we also define a slave process Pseudoterminal (allowing Aesop to control the terminal)\n\t\t\t\t\t\t\t\t\t\t\tconst pty: vscode.Pseudoterminal = {\n\t\t\t\t\t\t\t\t\t\t\t\tonDidWrite: scriptEmitter.event,\n\t\t\t\t\t\t\t\t\t\t\t\topen: () =>\tscriptEmitter.fire(bootScript),\n\t\t\t\t\t\t\t\t\t\t\t\tclose: () => {},\n\t\t\t\t\t\t\t\t\t\t\t\thandleInput: data => new vscode.ShellExecution(data)\n\t\t\t\t\t\t\t\t\t\t\t};\n\n\t\t\t\t\t\t\t\t\t\t\t//should this just be an active terminal/shellExecution?\n\t\t\t\t\t\t\t\t\t\t\tconst virtualTerminal = vscode.window.createTerminal({name: 'sb-runner', pty});\n\n//THIS WORKS, but we have no access to the DOM inside our webview//\n\t//now let's read SB's outputted index.html file, and parse out what we need\n\t\tfs.readFile(path.join(rootDir, '/node_modules/@storybook/core/dist/public/index.html'), (err, data) => {\n\t\t\tif (err) console.error(err);\n\t\t\telse {\n\t\t\t\tlet pulledHTML = data.toString();\n\t\t\t\tlet targetPoint = pulledHTML.indexOf('');\n\t\t\t\tlet firstHalf = pulledHTML.slice(0, targetPoint);\n\t\t\t\tlet secondHalf = pulledHTML.slice(targetPoint);\n\t\t\t\tpulledHTML = firstHalf.concat(payloadScript).concat(secondHalf);\n\t\t\t\tfs.writeFile(path.join(rootDir, '/node_modules/@storybook/core/dist/public/index.html'), pulledHTML, (err) => {\n\t\t\t\t\tif (err) console.error(err);\n\t\t\t\t\telse {\n\t\t\t\t\t\tvscode.window.showInformationMessage('Successfully injected script');\n\t\t\t\t\t};\n\t\t\t\t});\n\t\t\t}\n\t\t});\n\n\t//declare an empty array (of strings) to push our scripts to during the next part\n\t\tconst scriptArray : Array = [];\n\t\t//define a path to the root working directory of the user\n\t\tconst rootDir = fileURLToPath(vscode.workspace.workspaceFolders[0].uri.toString(true));\n\t\t//now let's read SB's outputted index.html file, and parse out what we need\n\t\tfs.readFile(path.join(rootDir, '/node_modules/@storybook/core/dist/public/index.html'), (err, data) => {\n\t\t\tif (err) console.error(err);\n\t\t\telse {\n\t\t\t\t//if we've read the HTML file, take its contents and stringify it\n\t\t\t\tlet outputFile = data.toString();\n\t\t\t\t// this log shows what our eventual permutations would look like as we carve out the scripts\n\t\t\t\t// vscode.window.showWarningMessage(`what's in it: ${outputFile.slice(outputFile.indexOf('')+6, outputFile.indexOf(''))} \\n`)\n\t\t\t\t//split out the body section of the retrieved html file\n\t\t\t\toutputFile = outputFile.slice(outputFile.indexOf('')+6, outputFile.indexOf(''));\n\t\t\t\tvscode.window.showWarningMessage(`${outputFile} \\n`)\n\n\t\t\t\t//this loop will peel out all the scripts so long as there are any to rip out\n\t\t\t\twhile (outputFile.includes(`\" tags behind\n\t\t\t\t\tlet temp = outputFile.slice(outputFile.indexOf(``));\n\t\t\t\t\tscriptArray.push(temp);\n\t\t\t\t\toutputFile = outputFile.slice(outputFile.indexOf(`\">`)+10);\n\t\t\t\t}\n\t\t\t};\n\t\t});\n\n
\n
\t\n\t
\n\t\n\t\n\t\n
\n\n\tdisposable = vscode.commands.registerCommand('extension.getStories', () => {\n\t\tbuild a command that retrieves Storybook files on startup\n\t\tcan be executed later if Storybook server is spun up after the extension opens\n\t\t\n\t\talso register this command at startup to crawl the file path\n\t\t${vscode.commands.executeCommand('extension.getStories')}\n\t\tvscode.window.showInformationMessage('Aesop is reading from your Storybook.');\n\n\t\tdefine a path to SB webpack bundle outputs (in user workspace /node_modules/ folder)\n\t\tif (vscode.workspace.workspaceFolders[0] !== undefined){\n\t\t\tconst distGlob = new vscode.RelativePattern(vscode.workspace.workspaceFolders[0], \"**(remove)/node_modules/@storybook/core/dist/public\");\n\t\t\t//instantiate a watcher to listen for fs path changes (e.g. file creation/update)\n\t\t\t//bools = options for ignoreCreateEvents?, ignoreChangeEvents?, ignoreDeleteEvents?\t\n\t\t\tconst observer = vscode.workspace.createFileSystemWatcher(distGlob, false, false, false);\n\t\t\t// observer.onDidChange = //resolve//;\t\t// observer.onDidCreate = //resolve//;\n\t\t\t//extract index.html file that outputs into SB's preview pane\n\t\t\tconst htmlGlob = new vscode.RelativePattern(vscode.workspace.workspaceFolders[0], \"*(remove)/node_modules/@storybook/core/dist/public/*.html\");\n\t\t\t//extract necessary bundle scripts to leverage in-app dependencies\n\t\t\tconst scriptGlob = new vscode.RelativePattern(vscode.workspace.workspaceFolders[0], \"*(remove)/node_modules/@storybook/core/dist/public/*.js\");\n\n\t\t\tconsole.log(vscode.Uri.file(fileURLToPath(`/node_modules/@storybook/core/dist/public`)));\n\n\t\t\t//do we need to resolve the Storybook UI script from the /dll/ folder?\n\t\t\t//if extract methods above fail, determine logic to parse out HTML/.js scripts (index 0?);\n\t\t\t//retrieve files with findFiles/relativeFilePath\n\t\t\tconst arrayOfScripts = vscode.workspace.findFiles(distGlob, null, 100);\n\t\t\t//dev check: have we successfully pulled down script files?\n\t\t\t//if so, should we then store them locally, or is there no point?\n\t\t\tif (arrayOfScripts !== undefined){\n\t\t\t\tvscode.window.showInformationMessage(\"Hey, dog: \" + `${arrayOfScripts}`);\n\t\t\t}\n\n\t\t\tvscode.window.showInformationMessage(`\n\t\t\trootPath: ${vscode.workspace.workspaceFolders[0]},\n\t\t\tvscode.Uri: ${vscode.Uri},\n\t\t\tworkspace: ${vscode.workspace},\n\t\t\tdistGlob: ${distGlob.toString()},\n\t\t\thtmlGlob: ${htmlGlob.toString()},\n\t\t\tscriptGlob: ${scriptGlob.toString()}\n\t\t\t`);\n\t\t};\n\n\t\tvscode.window.showInformationMessage(`\n\t\t\trootPath: ${vscode.workspace.workspaceFolders[0].uri.toString()},\\n\n\t\t\tvscode URI parseTest: ${vscode.Uri.parse('file://'+ '/node_modules/@storybook/core/dist/public/index.html')},\\n\n\t\t\tvscode URI parsed w escape: ${vscode.Uri.parse('file://'+ '/node_modules/\\@storybook/core/dist/public/index.html')},\\n\n\t\t\tvscode URI file Test: ${vscode.Uri.file('node_modules/@storybook/core/dist/public/index.html')}\n\t\t\t`);\n\t\t\t\n\t\tconsole.log(`\n\t\trootPath: ${vscode.workspace.workspaceFolders[0]},\n\t\tvscode.Uri: ${vscode.Uri},\n\t\tworkspace: ${vscode.workspace},\n\t\tfileSys: ${vscode.Uri.file(path.join('/'))}`);\n });\n */","module.exports = require(\"child_process\");","module.exports = require(\"fs\");","module.exports = require(\"os\");","module.exports = require(\"path\");","module.exports = require(\"url\");","module.exports = require(\"vscode\");"],"sourceRoot":""} \ No newline at end of file +{"version":3,"sources":["../webpack/bootstrap",".././node_modules/connected-domain/index.js",".././node_modules/connected-domain/lib/connected-domain.js",".././node_modules/ps-node/index.js",".././node_modules/ps-node/lib/index.js",".././node_modules/table-parser/index.js",".././node_modules/table-parser/lib/index.js",".././src/extension.ts","../external \"child_process\"","../external \"fs\"","../external \"os\"","../external \"path\"","../external \"url\"","../external \"vscode\""],"names":[],"mappings":";;QAAA;QACA;;QAEA;QACA;;QAEA;QACA;QACA;QACA;QACA;QACA;QACA;QACA;QACA;QACA;;QAEA;QACA;;QAEA;QACA;;QAEA;QACA;QACA;;;QAGA;QACA;;QAEA;QACA;;QAEA;QACA;QACA;QACA,0CAA0C,gCAAgC;QAC1E;QACA;;QAEA;QACA;QACA;QACA,wDAAwD,kBAAkB;QAC1E;QACA,iDAAiD,cAAc;QAC/D;;QAEA;QACA;QACA;QACA;QACA;QACA;QACA;QACA;QACA;QACA;QACA;QACA,yCAAyC,iCAAiC;QAC1E,gHAAgH,mBAAmB,EAAE;QACrI;QACA;;QAEA;QACA;QACA;QACA,2BAA2B,0BAA0B,EAAE;QACvD,iCAAiC,eAAe;QAChD;QACA;QACA;;QAEA;QACA,sDAAsD,+DAA+D;;QAErH;QACA;;;QAGA;QACA;;;;;;;;;;;;AClFA,iBAAiB,mBAAO,EAAE,uFAAwB,G;;;;;;;;;;;ACAlD;AACA;AACA;;AAEA;AACA,WAAW,MAAM;AACjB,WAAW,SAAS;AACpB,WAAW,QAAQ;AACnB,YAAY,OAAO,GAAG,YAAY,2BAA2B,aAAa,sBAAsB,EAAE,qCAAqC;AACvI;AACA;;AAEA;;AAEA;AACA;AACA;;AAEA;AACA;AACA;;AAEA;AACA;;AAEA;AACA;AACA;AACA;;AAEA;;AAEA;;AAEA;;AAEA;AACA;;AAEA;AACA;AACA;;AAEA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;;AAEA;AACA;;AAEA;;AAEA;;AAEA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,iBAAiB;;AAEjB;AACA;AACA;AACA;AACA;AACA;AACA;AACA,SAAS;AACT,KAAK;;AAEL;AACA;AACA;AACA;AACA,6BAA6B;AAC7B;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;;AAEA;AACA;AACA;AACA;;AAEA;AACA;;;AAGA;;AAEA;AACA;AACA;AACA;;AAEA;;AAEA;AACA;AACA;;AAEA;AACA;AACA;;AAEA;AACA;AACA;;AAEA;AACA;AACA;AACA,SAAS;;AAET;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA,wBAAwB;AACxB;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;;AAEA;;AAEA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;;AAEA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;;AAEA;AACA;;AAEA;;AAEA;AACA;AACA;AACA,aAAa;;AAEb;;AAEA;AACA;AACA;AACA;;AAEA;AACA,E;;;;;;;;;;;AC/PA,iBAAiB,mBAAO,CAAC,kDAAO;;;;;;;;;;;;ACAhC,mBAAmB,mBAAO,CAAC,oCAAe;AAC1C;AACA,kBAAkB,mBAAO,CAAC,0DAAc;AACxC;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,gBAAgB,mBAAO,CAAC,cAAI;;AAE5B;AACA;AACA,UAAU;AACV,WAAW,SAAS;AACpB,WAAW,SAAS;AACpB,WAAW,YAAY;AACvB,WAAW,SAAS;AACpB;;AAEA;AACA;;AAEA;AACA;AACA;;AAEA;AACA;AACA;;AAEA;AACA;AACA,KAAK;;AAEL;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA,KAAK;;AAEL;;AAEA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA,OAAO;;AAEP;AACA;AACA;;AAEA;AACA,KAAK;;AAEL;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA,KAAK;;AAEL;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA,KAAK;;AAEL;AACA;AACA;AACA;AACA;AACA;AACA;AACA,KAAK;AACL;AACA;;AAEA;AACA;AACA;AACA,WAAW,gBAAgB;AAC3B,WAAW,OAAO;AAClB,WAAW,OAAO;AAClB,WAAW,aAAa;AACxB,WAAW,SAAS;AACpB,WAAW,YAAY;AACvB,WAAW,SAAS;AACpB,YAAY;AACZ;;AAEA;;AAEA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA,KAAK;;AAEL;;;AAGA;AACA;AACA;;AAEA;AACA;AACA;;AAEA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;;AAEA;AACA;AACA;;AAEA;AACA;AACA;;AAEA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA,OAAO;;AAEP;AACA;AACA,GAAG;AACH;;AAEA;AACA;AACA;AACA,WAAW,cAAc;AACzB,WAAW,OAAO;AAClB,WAAW,OAAO;AAClB;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;;AAEA;;AAEA;AACA;AACA;;AAEA;AACA;AACA,GAAG;AACH;AACA;;AAEA;AACA;AACA;;AAEA;AACA,oBAAoB,WAAW;AAC/B;;AAEA;AACA;AACA;AACA,OAAO;AACP;AACA;AACA,OAAO;AACP;AACA;AACA;AACA;AACA,SAAS;AACT;AACA;AACA;AACA,KAAK;AACL;;AAEA;;AAEA;AACA;AACA;AACA,GAAG;AACH;;AAEA;AACA;AACA,WAAW,OAAO;AAClB;;AAEA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA,YAAY;AACZ;;AAEA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;;AAEA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA,OAAO;AACP;AACA,GAAG;;AAEH;AACA;;;;;;;;;;;;ACpSA,iBAAiB,mBAAO,EAAE,6DAAa,G;;;;;;;;;;;ACAvC;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,sBAAsB,mBAAO,CAAC,kEAAkB;AAChD;;AAEA;AACA;AACA;AACA,aAAa;AACb;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA,GAAG;;AAEH;AACA;AACA;;AAEA;AACA;AACA;;AAEA;AACA;;AAEA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,OAAO;AACP;AACA;AACA;AACA;AACA,GAAG;;AAEH;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,GAAG;;AAEH;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,GAAG;;AAEH;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;;AAEA;;AAEA;AACA;AACA;AACA;AACA;AACA,OAAO;;AAEP;AACA;AACA;AACA;AACA;AACA;AACA,SAAS;AACT;AACA;AACA,GAAG;;AAEH;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;;AAEA;AACA;;AAEA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;;AAEA;;AAEA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;;AAEA;AACA,GAAG;;AAEH;AACA;;AAEA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA,GAAG;;AAEH;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA,aAAa;AACb;AACA;AACA;AACA;AACA,yCAAyC;AACzC;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;;AAEA;AACA;;AAEA;;AAEA;;AAEA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;A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","file":"extension.js","sourcesContent":[" \t// The module cache\n \tvar installedModules = {};\n\n \t// The require function\n \tfunction __webpack_require__(moduleId) {\n\n \t\t// Check if module is in cache\n \t\tif(installedModules[moduleId]) {\n \t\t\treturn installedModules[moduleId].exports;\n \t\t}\n \t\t// Create a new module (and put it into the cache)\n \t\tvar module = installedModules[moduleId] = {\n \t\t\ti: moduleId,\n \t\t\tl: false,\n \t\t\texports: {}\n \t\t};\n\n \t\t// Execute the module function\n \t\tmodules[moduleId].call(module.exports, module, module.exports, __webpack_require__);\n\n \t\t// Flag the module as loaded\n \t\tmodule.l = true;\n\n \t\t// Return the exports of the module\n \t\treturn module.exports;\n \t}\n\n\n \t// expose the modules object (__webpack_modules__)\n \t__webpack_require__.m = modules;\n\n \t// expose the module cache\n \t__webpack_require__.c = installedModules;\n\n \t// define getter function for harmony exports\n \t__webpack_require__.d = function(exports, name, getter) {\n \t\tif(!__webpack_require__.o(exports, name)) {\n \t\t\tObject.defineProperty(exports, name, { enumerable: true, get: getter });\n \t\t}\n \t};\n\n \t// define __esModule on exports\n \t__webpack_require__.r = function(exports) {\n \t\tif(typeof Symbol !== 'undefined' && Symbol.toStringTag) {\n \t\t\tObject.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });\n \t\t}\n \t\tObject.defineProperty(exports, '__esModule', { value: true });\n \t};\n\n \t// create a fake namespace object\n \t// mode & 1: value is a module id, require it\n \t// mode & 2: merge all properties of value into the ns\n \t// mode & 4: return value when already ns object\n \t// mode & 8|1: behave like require\n \t__webpack_require__.t = function(value, mode) {\n \t\tif(mode & 1) value = __webpack_require__(value);\n \t\tif(mode & 8) return value;\n \t\tif((mode & 4) && typeof value === 'object' && value && value.__esModule) return value;\n \t\tvar ns = Object.create(null);\n \t\t__webpack_require__.r(ns);\n \t\tObject.defineProperty(ns, 'default', { enumerable: true, value: value });\n \t\tif(mode & 2 && typeof value != 'string') for(var key in value) __webpack_require__.d(ns, key, function(key) { return value[key]; }.bind(null, key));\n \t\treturn ns;\n \t};\n\n \t// getDefaultExport function for compatibility with non-harmony modules\n \t__webpack_require__.n = function(module) {\n \t\tvar getter = module && module.__esModule ?\n \t\t\tfunction getDefault() { return module['default']; } :\n \t\t\tfunction getModuleExports() { return module; };\n \t\t__webpack_require__.d(getter, 'a', getter);\n \t\treturn getter;\n \t};\n\n \t// Object.prototype.hasOwnProperty.call\n \t__webpack_require__.o = function(object, property) { return Object.prototype.hasOwnProperty.call(object, property); };\n\n \t// __webpack_public_path__\n \t__webpack_require__.p = \"\";\n\n\n \t// Load entry module and return exports\n \treturn __webpack_require__(__webpack_require__.s = \"./src/extension.ts\");\n","module.exports = require( './lib/connected-domain' );","/**\n * calculate all the connected domains based on the given two-dimensional array\n */\n\n/**\n * @param {Array} tdArray\n * @param {Function} indicator It receive the raw point data as the first parameter and decide what kind of domain the point belongs to, it should return a string as a domain identifier.\n * @param {Boolean} hardlink If use hard link. Default to false.\n * @return {Object} [{ bounding: { w: 12, h: 19, x: 0, y: 1 }, points: [ { x: 1, y: 2, point: {} } ], identifier: 'blue', domainId: 1 } ]\n */\nmodule.exports = function( tdArray, indicator, hardlink ){\n\n hardlink = hardlink || false;\n\n if( !tdArray ){\n throw new Error( 'tdArray must be provided' );\n }\n\n if( !indicator ){\n throw new Error( 'indicator must be provided' );\n }\n\n // clone 一份数据,因为需要对饮用进行修改,方便执行\n tdArray = JSON.parse( JSON.stringify( tdArray ) );\n\n // Result\n var domains = {};\n var domainUUID = 0;\n var pointsHash = {};\n\n // 遍历数组,划分domain\n\n tdArray.forEach(function( row, y ){\n\n row.forEach(function( colItem, x ){\n\n // get the current point identifier.\n var identifier = indicator( colItem, x, y );\n\n // get neighbours\n // Except for Undefined every data type is valid.\n var neighbours = [];\n\n // top neighbour\n if( tdArray[ y - 1 ] && tdArray[ y - 1 ][ x ] !== undefined ){\n neighbours.push( pointsHash[ x + '_' + ( y - 1 ) ] );\n }\n\n // left neighbour\n if( row[ x - 1 ] !== undefined ){\n neighbours.push( pointsHash[ ( x - 1 ) + '_' + y ] );\n }\n\n // soft link will treat corner link as domain link.\n if( !hardlink ){\n // top left neighbour\n if( tdArray[ y - 1 ] && tdArray[ y - 1 ][ x - 1 ] !== undefined ){\n neighbours.push( pointsHash[ ( x - 1 ) + '_' + ( y - 1 ) ] );\n }\n\n // top right neighbour\n if( tdArray[ y - 1 ] && tdArray[ y - 1 ][ x + 1 ] !== undefined ){\n neighbours.push( pointsHash[ ( x + 1 ) + '_' + ( y - 1 ) ] );\n }\n }\n\n if( neighbours.length ){\n var matched = false;\n\n neighbours.forEach(function( neighbour ){\n\n if( neighbour.identifier == identifier ){\n\n // If the neighbour is the first neighbour has the same identifier\n if( !matched ){\n addPointToDomain( colItem, x, y, neighbour.domainId );\n matched = true;\n }\n\n // If more than one neighbour matched, check if these neighbours belong to the same domain\n // If not, merge these domains since they connects to each other.\n else {\n var colItemPoint = pointsHash[ x + '_' + y ];\n if( neighbour.domainId != colItemPoint.domainId ){\n mergeDomains( neighbour.domainId, colItemPoint.domainId );\n }\n }\n }\n });\n\n if( !matched ){\n addNewDomain( colItem, x, y, identifier );\n }\n }\n else {\n addNewDomain( colItem, x, y, identifier );\n }\n });\n });\n\n // some summary\n var result = {\n domains: [],\n totalDomains: 0,\n groupByIdentifier: {},\n totalIdentifiers: 0\n };\n\n var domainId = null;\n var identifier = null;\n var domain = null;\n for( domainId in domains ){\n domain = domains[ domainId ];\n domain.bounding = calculateBounding( domain.points );\n identifier = domain.identifier;\n\n result.domains.push( domain );\n result.totalDomains++;\n\n if( !( identifier in result.groupByIdentifier ) ){\n result.groupByIdentifier[ identifier ] = [];\n result.totalIdentifiers++;\n }\n\n result.groupByIdentifier[ identifier ].push( domain );\n }\n\n\n function calculateBounding( points ){\n\n var minX = null;\n var minY = null;\n var maxX = null;\n var maxY = null;\n\n points.forEach(function( point ){\n\n if( minX === null || point.x < minX ){\n minX = point.x;\n }\n\n if( minY === null || point.y < minY ){\n minY = point.y;\n }\n\n if( maxX === null || point.x > maxX ){\n maxX = point.x;\n }\n\n if( maxY === null || point.y > maxY ){\n maxY = point.y;\n }\n });\n\n var w = maxX - minX;\n var h = maxY - minY;\n\n return {\n x: minX,\n y: minY,\n w: w,\n h: h\n };\n }\n\n /**\n *\n * @param point\n * @param x\n * @param y\n * @param identifier\n */\n function addNewDomain( point, x, y, identifier ){\n\n var newDomain = {\n identifier: identifier,\n domainId: ++domainUUID,\n bounding: {},\n points: []\n };\n\n var newPoint = {\n value: point,\n x: x,\n y: y,\n identifier: identifier,\n domainId: newDomain.domainId\n };\n\n pointsHash[ x + '_' + y ] = {\n value: point,\n identifier: identifier,\n domainId: newDomain.domainId\n };\n\n newDomain.points.push( newPoint );\n\n domains[ newDomain.domainId ] = newDomain;\n }\n\n /**\n * add a point to a existing domain, and attach properties domainId and identifier to point.\n * @param point\n * @param x\n * @param y\n * @param domainId\n */\n function addPointToDomain( point, x, y, domainId ){\n\n var domain = domains[ domainId ];\n var newPoint = {\n value: point,\n x: x,\n y: y,\n identifier: domain.identifier,\n domainId: domainId\n };\n\n pointsHash[ x + '_' + y ] = {\n value: point,\n identifier: domain.identifier,\n domainId: domainId\n };\n\n domain.points.push( newPoint );\n }\n\n /**\n * 将 domainB 合并到 domainA\n * @param domainAId\n * @param domainBId\n */\n function mergeDomains( domainAId, domainBId ){\n\n var domainA = domains[ domainAId ];\n var domainB = domains[ domainBId ];\n\n if( domainA.identifier == domainB.identifier ){\n // 更新 domainB 的domainId\n\n domainB.domainId = domainA.domainId;\n\n domainB.points.forEach(function( point ){\n point.domainId = domainA.domainId;\n pointsHash[ point.x + '_' + point.y ].domainId = domainA.domainId;\n });\n\n domainA.points = domainA.points.concat( domainB.points );\n\n // 删除domainB\n delete domains[ domainBId ];\n }\n }\n\n return result;\n};","module.exports = require('./lib');\n","var ChildProcess = require('child_process');\nvar IS_WIN = process.platform === 'win32';\nvar TableParser = require('table-parser');\n/**\n * End of line.\n * Basically, the EOL should be:\n * - windows: \\r\\n\n * - *nix: \\n\n * But i'm trying to get every possibilities covered.\n */\nvar EOL = /(\\r\\n)|(\\n\\r)|\\n|\\r/;\nvar SystemEOL = require('os').EOL;\n\n/**\n * Execute child process\n * @type {Function}\n * @param {String[]} args\n * @param {Function} callback\n * @param {Object=null} callback.err\n * @param {Object[]} callback.stdout\n */\n\nvar Exec = module.exports = exports = function (args, callback) {\n var spawn = ChildProcess.spawn;\n\n // on windows, if use ChildProcess.exec(`wmic process get`), the stdout will gives you nothing\n // that's why I use `cmd` instead\n if (IS_WIN) {\n\n var CMD = spawn('cmd');\n var stdout = '';\n var stderr = null;\n\n CMD.stdout.on('data', function (data) {\n stdout += data.toString();\n });\n\n CMD.stderr.on('data', function (data) {\n\n if (stderr === null) {\n stderr = data.toString();\n }\n else {\n stderr += data.toString();\n }\n });\n\n CMD.on('exit', function () {\n\n var beginRow;\n stdout = stdout.split(EOL);\n\n // Find the line index for the titles\n stdout.forEach(function (out, index) {\n if (out && typeof beginRow == 'undefined' && out.indexOf('CommandLine') === 0) {\n beginRow = index;\n }\n });\n\n // get rid of the start (copyright) and the end (current pwd)\n stdout.splice(stdout.length - 1, 1);\n stdout.splice(0, beginRow);\n\n callback(stderr, stdout.join(SystemEOL) || false);\n });\n\n CMD.stdin.write('wmic process get ProcessId,ParentProcessId,CommandLine \\n');\n CMD.stdin.end();\n }\n else {\n if (typeof args === 'string') {\n args = args.split(/\\s+/);\n }\n const child = spawn('ps', args);\n var stdout = '';\n var stderr = null;\n\n child.stdout.on('data', function (data) {\n stdout += data.toString();\n });\n\n child.stderr.on('data', function (data) {\n\n if (stderr === null) {\n stderr = data.toString();\n }\n else {\n stderr += data.toString();\n }\n });\n\n child.on('exit', function () {\n if (stderr) {\n return callback(stderr.toString());\n }\n else {\n callback(null, stdout || false);\n }\n });\n }\n};\n\n/**\n * Query Process: Focus on pid & cmd\n * @param query\n * @param {String|String[]} query.pid\n * @param {String} query.command RegExp String\n * @param {String} query.arguments RegExp String\n * @param {String|array} query.psargs\n * @param {Function} callback\n * @param {Object=null} callback.err\n * @param {Object[]} callback.processList\n * @return {Object}\n */\n\nexports.lookup = function (query, callback) {\n\n /**\n * add 'lx' as default ps arguments, since the default ps output in linux like \"ubuntu\", wont include command arguments\n */\n var exeArgs = query.psargs || ['lx'];\n var filter = {};\n var idList;\n\n // Lookup by PID\n if (query.pid) {\n\n if (Array.isArray(query.pid)) {\n idList = query.pid;\n }\n else {\n idList = [query.pid];\n }\n\n // Cast all PIDs as Strings\n idList = idList.map(function (v) {\n return String(v);\n });\n\n }\n\n\n if (query.command) {\n filter['command'] = new RegExp(query.command, 'i');\n }\n\n if (query.arguments) {\n filter['arguments'] = new RegExp(query.arguments, 'i');\n }\n\n if (query.ppid) {\n filter['ppid'] = new RegExp(query.ppid);\n }\n\n return Exec(exeArgs, function (err, output) {\n if (err) {\n return callback(err);\n }\n else {\n var processList = parseGrid(output);\n var resultList = [];\n\n processList.forEach(function (p) {\n\n var flt;\n var type;\n var result = true;\n\n if (idList && idList.indexOf(String(p.pid)) < 0) {\n return;\n }\n\n for (type in filter) {\n flt = filter[type];\n result = flt.test(p[type]) ? result : false;\n }\n\n if (result) {\n resultList.push(p);\n }\n });\n\n callback(null, resultList);\n }\n });\n};\n\n/**\n * Kill process\n * @param pid\n * @param {Object|String} signal\n * @param {String} signal.signal\n * @param {number} signal.timeout\n * @param next\n */\n\nexports.kill = function( pid, signal, next ){\n //opts are optional\n if(arguments.length == 2 && typeof signal == 'function'){\n next = signal;\n signal = undefined;\n }\n\n var checkTimeoutSeconds = (signal && signal.timeout) || 30;\n\n if (typeof signal === 'object') {\n signal = signal.signal;\n }\n\n try {\n process.kill(pid, signal);\n } catch(e) {\n return next && next(e);\n }\n\n var checkConfident = 0;\n var checkTimeoutTimer = null;\n var checkIsTimeout = false;\n\n function checkKilled(finishCallback) {\n exports.lookup({ pid: pid }, function(err, list) {\n if (checkIsTimeout) return;\n\n if (err) {\n clearTimeout(checkTimeoutTimer);\n finishCallback && finishCallback(err);\n } else if(list.length > 0) {\n checkConfident = (checkConfident - 1) || 0;\n checkKilled(finishCallback);\n } else {\n checkConfident++;\n if (checkConfident === 5) {\n clearTimeout(checkTimeoutTimer);\n finishCallback && finishCallback();\n } else {\n checkKilled(finishCallback);\n }\n }\n });\n }\n\n next && checkKilled(next);\n\n checkTimeoutTimer = next && setTimeout(function() {\n checkIsTimeout = true;\n next(new Error('Kill process timeout'));\n }, checkTimeoutSeconds * 1000);\n};\n\n/**\n * Parse the stdout into readable object.\n * @param {String} output\n */\n\nfunction parseGrid(output) {\n if (!output) {\n return [];\n }\n return formatOutput(TableParser.parse(output));\n}\n\n/**\n * format the structure, extract pid, command, arguments, ppid\n * @param data\n * @return {Array}\n */\n\nfunction formatOutput(data) {\n var formatedData = [];\n data.forEach(function (d) {\n var pid = ( d.PID && d.PID[0] ) || ( d.ProcessId && d.ProcessId[0] ) || undefined;\n var cmd = d.CMD || d.CommandLine || d.COMMAND || undefined;\n var ppid = ( d.PPID && d.PPID[0] ) || ( d.ParentProcessId && d.ParentProcessId[0] ) || undefined;\n\n if (pid && cmd) {\n var command = cmd[0];\n var args = '';\n\n if (cmd.length > 1) {\n args = cmd.slice(1);\n }\n\n formatedData.push({\n pid: pid,\n command: command,\n arguments: args,\n ppid: ppid\n });\n }\n });\n\n return formatedData;\n}\n","module.exports = require( './lib/index' );","/**\n *\n * 1, define the edge ( begin and end ) of every title field\n * 2, parse all the lines except the title line, get all the connected-domains\n * 3, group all the connected-domains vertically overlapped.\n * 4, a domain group belongs to a title field if they vertically overlapped\n * 5, calculate all the edge info through the group domain and title field relations.\n */\nvar ConnectedDomain = require('connected-domain');\nvar EMPTY_EX = /\\s/;\n\n/**\n * The output sting of cmd to parse\n * @param output\n * @returns {Array}\n */\nmodule.exports.parse = function (output) {\n\n // Split into lines\n // Basically, the EOL should be:\n // - windows: \\r\\n\n // - *nix: \\n\n // But i'm trying to get every possibilities covered.\n var linesTmp = output.split(/(\\r\\n)|(\\n\\r)|\\n|\\r/);\n\n // valid lines\n var lines = [];\n // title field info, mapped with filed name.\n var titleInfo = {};\n // the two dimensional array of the lines\n var twoDimArray = [];\n\n // get rid of all the empty lines.\n linesTmp.forEach(function (line) {\n if (line && line.trim()) {\n lines.push(line);\n }\n });\n\n // build title fields edge info\n // build two dimensional array for Connected-Domain to parse.\n lines.forEach(function (line, index) {\n\n // Treat the first line as the title fields line\n if (index == 0) {\n var fields = line.split(/\\s+/);\n\n // record the beginning and ending for each field\n fields.forEach(function (field, idx) {\n\n if (field) {\n var info = titleInfo[field] = {};\n var indexBegin = line.indexOf(field);\n var indexEnd = indexBegin + field.length;\n\n if (idx == 0) {\n info.titleBegin = 0;\n }\n else {\n info.titleBegin = indexBegin;\n }\n\n if (idx == fields.length - 1) {\n info.titleEnd = line.length - 1;\n }\n else {\n info.titleEnd = indexEnd;\n }\n }\n });\n }\n else {\n twoDimArray[index - 1] = line.split('');\n }\n });\n\n // In the connected-domain aspect of view, all the blanks are connected, and all the non-blanks are connected.\n var connectedDomains = ConnectedDomain(twoDimArray, function (value) {\n if (EMPTY_EX.test(value)) {\n return -1;\n }\n else {\n return 1;\n }\n }, true);\n\n // all the connected domains grouped if they are vertically overlapped.\n var valuesDomainsVerticalGroups = [];\n\n // sore the domain list make 'x' in ascending order, it will prevent the situation that:\n // 1, two domains are not overlapped, so two groups are created for them at first\n // 2, another domain is found overlapped with both of the domains at the first step.\n // 3, In this situation the three groups have to be merged, which is complicated to implement.\n //\n // If the list is sorted in this order, this situation can't happen, because:\n // - 1, If two non-overlapped domains A, B ( the \"x\" value of A less than B ) are found first.\n // - 2, Since the list is in 'x' ascending order, the 'x' values of the following domains must larger or equal to the \"x\" of B, which means they will never overlapped with domain A.\n // - 3, So this situation can't happen.\n connectedDomains.domains.sort(function (a, b) {\n return a.bounding.x - b.bounding.x;\n });\n\n // Group domains vertically overlapped.\n connectedDomains.domains.forEach(function (domain) {\n // only handle un-empty domain\n if (domain.identifier === 1) {\n var overlapped = false;\n\n // If overlapped\n valuesDomainsVerticalGroups.forEach(function (group) {\n var bounding = domain.bounding;\n var left = bounding.x;\n var right = bounding.x + bounding.w;\n\n if (overlap(left, right, group.begin, group.end)) {\n\n overlapped = true;\n group.domains.push(domain);\n group.begin = group.begin > left ? left : group.begin;\n group.end = group.end < right ? right : group.end;\n }\n });\n\n // If not overlapped with any group, then create a new group\n if (!overlapped) {\n valuesDomainsVerticalGroups.push({\n begin: domain.bounding.x,\n end: domain.bounding.x + domain.bounding.w,\n domains: [domain]\n });\n }\n }\n });\n\n // connect all the groups to the title fields\n valuesDomainsVerticalGroups.forEach(function (group) {\n var title = null;\n var info = null;\n var overlapped = false;\n\n var minimunLeftDistance = null;\n var nearestLeftTitle = null;\n var distance = null;\n\n for (title in titleInfo) {\n info = titleInfo[title];\n\n /**\n * The calculation below is to find the nearest left title field to the group, in case no overlapped title field found.\n */\n if (group.begin > info.titleBegin) {\n distance = group.begin - info.titleBegin;\n\n if (!nearestLeftTitle || ( distance < minimunLeftDistance )) {\n nearestLeftTitle = title;\n minimunLeftDistance = distance;\n }\n }\n\n if (overlap(group.begin, group.end, info.titleBegin, info.titleEnd)) {\n\n overlapped = true;\n info.titleBegin = info.titleBegin > group.begin ? group.begin : info.titleBegin;\n info.titleEnd = info.titleEnd < group.end ? group.end : info.titleEnd;\n }\n }\n\n // Groups not match any title field belongs to the nearest left title field\n if (!overlapped && nearestLeftTitle) {\n var nearestTitleField = titleInfo[nearestLeftTitle];\n nearestTitleField.titleBegin = nearestTitleField.titleBegin > group.begin ? group.begin : nearestTitleField.titleBegin;\n nearestTitleField.titleEnd = nearestTitleField.titleEnd < group.end ? group.end : nearestTitleField.titleEnd;\n\n }\n });\n\n // The final result\n var result = [];\n\n // Since we have got all the title bounding edges, we can split all the lines into values now\n lines.forEach(function (line, index) {\n // skip the first line\n if (index > 0) {\n\n var lineItem = {};\n var title = null;\n var info = null;\n var value = null;\n for (title in titleInfo) {\n info = titleInfo[title];\n value = line.substring(info.titleBegin, info.titleEnd + 1);\n lineItem[title] = splitValue(value.trim());\n }\n\n result.push(lineItem);\n }\n });\n\n return result;\n};\n\n/**\n * Test if two bounding overlapped vertically\n * @param begin1\n * @param end1\n * @param begin2\n * @param end2\n * @returns {boolean}\n */\nfunction overlap(begin1, end1, begin2, end2) {\n return ( begin1 > begin2 && begin1 < end2 ) || // 2--1--2--1 or 2--1--1--2\n ( end1 > begin2 && end1 < end2 ) || // 1--2--1--2 or 2--1--1--2\n ( begin1 <= begin2 && end1 >= end2 );// 21--12 or 1--2--2--1\n}\n\n/**\n * transform a string value into array. It's not just split(), but also to consider some chunk that wrapped with `\"`, like below:\n * \"C:\\Program Files\\Google\\Chrome\\Application\\chrome.exe\" --type=renderer --lang=zh-CN, `C:\\Program Files\\Google\\Chrome\\Application\\chrome.exe` should be treated as a whole,\n * also, be careful don't be mislead by format like `--name=\"neekey\"`, even more complicated: `--name=\"Neekey Ni\"`\n * so, `\"C:\\Program Files\\Internet Explorer\\iexplore.exe\" --name=\"Jack Neekey\"` should split into:\n * - C:\\Program Files\\Internet Explorer\\iexplore.exe // without `\"`\n * - --name=\"Jack Neekey\" // with `\"`\n */\nfunction splitValue(value) {\n\n var match = value.match(/\"/g);\n\n // If only one \" found, then just ignore it\n if (!match || match.length == 1) {\n return value.split(/\\s+/);\n }\n else {\n var result = [];\n var chunk = null;\n var ifInWrappedChunk = false;\n var ifInPureWrappedChunk = false;\n var quotaCount = 0;\n\n // If the match length is a even, than nothing special, if a odd, ignore the last one.\n var maxQuotaCount = match.length % 2 == 0 ? match.length : match.length - 1;\n\n var previousItem = null;\n var values = value.split('');\n\n values.forEach(function (item, index) {\n\n if (item !== ' ') {\n\n if (item === '\"') {\n // quota chunk begin\n if (ifInWrappedChunk === false && quotaCount <= maxQuotaCount) {\n ifInWrappedChunk = true;\n quotaCount++;\n\n // pure quota chunk begin\n if (previousItem === ' ' || previousItem === null) {\n ifInPureWrappedChunk = true;\n chunk = '';\n }\n // normal continue\n else {\n chunk += item;\n }\n }\n // quota chunk end\n else if (ifInWrappedChunk === true) {\n ifInWrappedChunk = false;\n quotaCount++;\n\n // pure quota chunk end\n if (ifInPureWrappedChunk === true) {\n ifInPureWrappedChunk = false;\n result.push(chunk);\n chunk = null;\n }\n // normal continue\n else {\n chunk += item;\n }\n }\n }\n // normal begin\n else if (ifInWrappedChunk === false && ( previousItem === ' ' || previousItem === null )) {\n chunk = item;\n }\n // normal or quota chunk continue.\n else {\n chunk += item;\n }\n }\n // quota chunk continue, in quota chunk, blank is valid.\n else if (ifInWrappedChunk) {\n chunk += item;\n }\n // if not in quota chunk, them a blank means an end. But make sure chunk is exist, cause that could be blanks at the beginning.\n else if (chunk !== null) {\n result.push(chunk);\n chunk = null;\n }\n\n previousItem = item;\n\n // If this is the last one, but chunk is not end\n if (index == ( values.length - 1 ) && chunk !== null) {\n result.push(chunk);\n chunk = null;\n }\n });\n\n return result;\n }\n}\n","import * as vscode from 'vscode';\nimport { fileURLToPath } from 'url';\nimport * as path from 'path';\nimport * as fs from 'fs';\nimport * as ps from 'ps-node';\n\nexport function activate(context: vscode.ExtensionContext) {\n\n\tlet PORT = 6006;\n\tconst host = 'localhost';\n\tlet dependencyFound = false;\n\tlet foundSb = false;\n\t\n //create disposable variable type, registers awaken command & opens webview\n\tlet disposable = vscode.commands.registerCommand('extension.aesopAwaken', () => {\n\t\t\n\t\t//define a path to the root working directory of the user\n\t\tconst rootDir = fileURLToPath(vscode.workspace.workspaceFolders[0].uri.toString(true));\n\n\t\t//check first to ensure that Storybook has been depended into the current working directory\n\t\tfs.access(path.join(rootDir, '/node_modules/@storybook'), (err) => {\n\t\t\t//if the filepath isn't found, show the user what Aesop is reading as the root path\n\t\t\tif (err) {\n\t\t\t\tvscode.window.showErrorMessage(`Aesop could not find Storybook as a dependency in the active folder, ${rootDir}`);\n\t\t\t}\telse {\n\t\t\t\tdependencyFound = true;\n\t\t\t}\n\t\t});\n\n\t\tif (dependencyFound === true && foundSb === false){\n\t\t\t//check to see if a storybook node process is already running\n\t\t\tps.lookup({\n\t\t\t\tcommand: 'node',\n\t\t\t\tpsargs: 'ux'},\n\t\t\t\t(err, resultList) => {\n\t\t\t\tif (err){\n\t\t\t\t\t\tvscode.window.showErrorMessage(`Failed looking for running Node processes. Error: ${err}`);\n\t\t\t\t} else {\n\t\t\t\t\t//if the process lookup was able to find running processes, iterate through to review them\n\t\t\t\t\tresultList.forEach((process) => {\n\n\t\t\t\t\t\t// ---> OUTPUT LOGGER <--- //\n\t\t\t\t\t\tfs.writeFile(path.join(rootDir, 'YOLO.txt'),\n\t\t\t\t\t\t`YOLO, fam:\\n\\n\\n\\n`,\n\t\t\t\t\t\t(err) => {console.log(`Couldn't output process information to YOLO.txt: ${err}`)});\n\t\t\t\t\t\tvscode.window.showInformationMessage('Check YOLO.txt for output information');\n\n\t\t\t\t\t\t//check if any running processes are using the start-storybook script\n\t\t\t\t\t\tif(process.arguments[0].includes('storybook')){\n\t\t\t\t\t\t\tfoundSb = true;\n\t\t\t\t\t\t\t//stretch goal: check for multiple instances of storybook and reconcile\n\t\t\t\t\t\t\t//if so, extract port number and use that value to populate the webview with that contents\n\t\t\t\t\t\t\n\t\t\t\t\t\t\tconst pFlagIndex = process.arguments.indexOf('-p');\n\t\t\t\t\t\t\tif (pFlagIndex !== -1){\n\t\t\t\t\t\t\t\tPORT = Number(process.arguments[pFlagIndex+1]);\n\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\t// ---> OUTPUT LOGGER <--- //\n\t\t\t\t\t\t\tfs.appendFile(path.join(rootDir, 'YOLO.txt'), `This process matches for 'storybook' search string:\\n\\n\n\t\t\t\t\t\t\tPID: ${process.pid}, COMMAND:${process.command}, ARGUMENTS: ${process.arguments}\\n\\nPORT has been assigned to: ${PORT}`, (err) => {console.log(err)});\n\t\t\t\t\t\t}\n\t\t\t\t\t})\n\t\t\t\t}\n\t\t\t})\n\t\t};\n\n\t\tif (dependencyFound === true && foundSb === false){\n\t\t\t//if no processes match 'storybook', we will have to spin up the storybook server\n\t\t\t//starts by extracting the existing storybook script in the package.json\n\t\t\tfs.readFile(path.join(rootDir, 'package.json'), (err, data) => {\n\t\t\t\tif (err){\n\t\t\t\t\tvscode.window.showErrorMessage(`Does this root folder contain a \"package.json\" file?`);\n\t\t\t\t}\telse {\n\t\t\t\t\t//enter the package.JSON file and retrieve its contents as a string\n\t\t\t\t\tlet packageJSON = JSON.parse(data.toString());\n\t\t\t\t\tlet storybookScript = packageJSON.scripts.storybook;\n\n\t\t\t\t\t// // ---> OUTPUT LOGGER <--- //\n\t\t\t\t\t// fs.appendFile(path.join(rootDir, 'YOLO.txt'), `Here is the JSON parsed version:\\n\n\t\t\t\t\t// ${packageJSON.scripts}\\n\n\t\t\t\t\t// ${storybookScript}`, (err) => {console.log(err)});\n\n\t\t\t\t\t//iterate through that text string and parse out important flags\n\t\t\t\t\t//it is more helpful to split it into an array separated by whitespace to grab these\n\t\t\t\t\tlet retrievedScriptArray = storybookScript.split(' ');\n\t\t\t\t\tfor (let i = 0; i < retrievedScriptArray.length; i++){\n\t\t\t\t\t\t//add flags\n\t\t\t\t\t\tif (retrievedScriptArray[i] === '-p'){\n\t\t\t\t\t\t\tPORT = parseInt(retrievedScriptArray[i+1]);\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t});\n\n\t\t\t//execute Ola's logic to launch the child process, passing rootDir as an options arg\n\n\t\t}\n\n\t\t//set the extension context equal to \"aesop is running\"\n\t\t// vscode.commands.executeCommand(\"setContext\", \"is-running-aesop\", true);\n\n\t\t//still inside our disposable variable, let's create the webview panel\n\t\tconst panel = vscode.window.createWebviewPanel(\n\t\t\t'aesop-sb',\n\t\t\t'Aesop',\n\t\t\tvscode.ViewColumn.Two,\n\t\t\t{\n\t\t\t\tenableCommandUris: true,\n\t\t\t\tenableScripts: true,\n\t\t\t\tportMapping: [\n\t\t\t\t\t{ webviewPort: PORT, extensionHostPort: PORT}\n\t\t\t\t]\n\t\t\t}\n\t\t);\n\n\t\tpanel.webview.html =\n\t\t`\n\t\t\n\t\t\t\n\t\t\t\t\n\t\t\t\t\t\n\t\t\t\t\t\n\t\t\t\t\tAesop\n\t\t\t\t\n\t\t\t\t\n\t\t\t\t\t\n\t\t\t\t\n\t\t\t\n\t\t`\n\t})\n\n\tcontext.subscriptions.push(disposable);\n};\n\nexport function deactivate() {\n\t\n}\n\n/*\nto-do:\n\tfigure out how to iteratively call sb scripts within our webview\n\twebview messages / scripts to reload\n\tfigure out how to use a tsx rule in webpack to execute scripts\n\tsignal babel to interpret this block as tsx, e.g. something like: //@tsx babel//\n\n\n\t\n\t\t\t\t\t\tvscode.tasks.registerTaskProvider('runStorybook', {\n\t\t\t\t\t\t\t\t\t\t\t\tprovideTasks(token?: vscode.CancellationToken) {\n\t\t\t\t\t\t\t\t\t\t\t\t\t\treturn [\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tnew vscode.Task({type: 'runStorybook'}, vscode.TaskScope.Workspace,\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\"Aesop Chronicle\", \"aesop\", new vscode.ShellExecution(`npm run storybook --ci`))\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t];\n\t\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\tresolveTask(task: vscode.Task, token?: vscode.CancellationToken) {\n\t\t\t\t\t\t\t\t\t\t\t\t\t\treturn task;\n\t\t\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t\t\t});\n\n\t\t\t\t\t\t\t\t\t\t\t//define the script text to execute to the virtual terminal instance\n\t\t\t\t\t\t\t\t\t\t\tconst bootScript = `storybook --ci`;\n\t\t\t\t\t\t\t\t\t\t\tconst bootStorybook = new vscode.ProcessExecution(bootScript, {cwd: rootDir});\n\n\t\t\t\t\t\t\t\t\t\t\t//now create a virtual terminal and execute our special npm script for it\n\t\t\t\t\t\t\t\t\t\t\t//this first requires creating an eventEmitter that will fire that script\n\t\t\t\t\t\t\t\t\t\t\tconst scriptEmitter = new vscode.EventEmitter();\n\t\t\t\t\t\t\t\n\t\t\t\t\t\t\t\t\t\t\t//we also define a slave process Pseudoterminal (allowing Aesop to control the terminal)\n\t\t\t\t\t\t\t\t\t\t\tconst pty: vscode.Pseudoterminal = {\n\t\t\t\t\t\t\t\t\t\t\t\tonDidWrite: scriptEmitter.event,\n\t\t\t\t\t\t\t\t\t\t\t\topen: () =>\tscriptEmitter.fire(bootScript),\n\t\t\t\t\t\t\t\t\t\t\t\tclose: () => {},\n\t\t\t\t\t\t\t\t\t\t\t\thandleInput: data => new vscode.ShellExecution(data)\n\t\t\t\t\t\t\t\t\t\t\t};\n\n\t\t\t\t\t\t\t\t\t\t\t//should this just be an active terminal/shellExecution?\n\t\t\t\t\t\t\t\t\t\t\tconst virtualTerminal = vscode.window.createTerminal({name: 'sb-runner', pty});\n\n//THIS WORKS, but we have no access to the DOM inside our webview//\n\t//now let's read SB's outputted index.html file, and parse out what we need\n\t\tfs.readFile(path.join(rootDir, '/node_modules/@storybook/core/dist/public/index.html'), (err, data) => {\n\t\t\tif (err) console.error(err);\n\t\t\telse {\n\t\t\t\tlet pulledHTML = data.toString();\n\t\t\t\tlet targetPoint = pulledHTML.indexOf('');\n\t\t\t\tlet firstHalf = pulledHTML.slice(0, targetPoint);\n\t\t\t\tlet secondHalf = pulledHTML.slice(targetPoint);\n\t\t\t\tpulledHTML = firstHalf.concat(payloadScript).concat(secondHalf);\n\t\t\t\tfs.writeFile(path.join(rootDir, '/node_modules/@storybook/core/dist/public/index.html'), pulledHTML, (err) => {\n\t\t\t\t\tif (err) console.error(err);\n\t\t\t\t\telse {\n\t\t\t\t\t\tvscode.window.showInformationMessage('Successfully injected script');\n\t\t\t\t\t};\n\t\t\t\t});\n\t\t\t}\n\t\t});\n\n\t//declare an empty array (of strings) to push our scripts to during the next part\n\t\tconst scriptArray : Array = [];\n\t\t//define a path to the root working directory of the user\n\t\tconst rootDir = fileURLToPath(vscode.workspace.workspaceFolders[0].uri.toString(true));\n\t\t//now let's read SB's outputted index.html file, and parse out what we need\n\t\tfs.readFile(path.join(rootDir, '/node_modules/@storybook/core/dist/public/index.html'), (err, data) => {\n\t\t\tif (err) console.error(err);\n\t\t\telse {\n\t\t\t\t//if we've read the HTML file, take its contents and stringify it\n\t\t\t\tlet outputFile = data.toString();\n\t\t\t\t// this log shows what our eventual permutations would look like as we carve out the scripts\n\t\t\t\t// vscode.window.showWarningMessage(`what's in it: ${outputFile.slice(outputFile.indexOf('')+6, outputFile.indexOf(''))} \\n`)\n\t\t\t\t//split out the body section of the retrieved html file\n\t\t\t\toutputFile = outputFile.slice(outputFile.indexOf('')+6, outputFile.indexOf(''));\n\t\t\t\tvscode.window.showWarningMessage(`${outputFile} \\n`)\n\n\t\t\t\t//this loop will peel out all the scripts so long as there are any to rip out\n\t\t\t\twhile (outputFile.includes(`\" tags behind\n\t\t\t\t\tlet temp = outputFile.slice(outputFile.indexOf(``));\n\t\t\t\t\tscriptArray.push(temp);\n\t\t\t\t\toutputFile = outputFile.slice(outputFile.indexOf(`\">`)+10);\n\t\t\t\t}\n\t\t\t};\n\t\t});\n\n
\n
\t\n\t
\n\t\n\t\n\t\n
\n\n\tdisposable = vscode.commands.registerCommand('extension.getStories', () => {\n\t\tbuild a command that retrieves Storybook files on startup\n\t\tcan be executed later if Storybook server is spun up after the extension opens\n\t\t\n\t\talso register this command at startup to crawl the file path\n\t\t${vscode.commands.executeCommand('extension.getStories')}\n\t\tvscode.window.showInformationMessage('Aesop is reading from your Storybook.');\n\n\t\tdefine a path to SB webpack bundle outputs (in user workspace /node_modules/ folder)\n\t\tif (vscode.workspace.workspaceFolders[0] !== undefined){\n\t\t\tconst distGlob = new vscode.RelativePattern(vscode.workspace.workspaceFolders[0], \"**(remove)/node_modules/@storybook/core/dist/public\");\n\t\t\t//instantiate a watcher to listen for fs path changes (e.g. file creation/update)\n\t\t\t//bools = options for ignoreCreateEvents?, ignoreChangeEvents?, ignoreDeleteEvents?\t\n\t\t\tconst observer = vscode.workspace.createFileSystemWatcher(distGlob, false, false, false);\n\t\t\t// observer.onDidChange = //resolve//;\t\t// observer.onDidCreate = //resolve//;\n\t\t\t//extract index.html file that outputs into SB's preview pane\n\t\t\tconst htmlGlob = new vscode.RelativePattern(vscode.workspace.workspaceFolders[0], \"*(remove)/node_modules/@storybook/core/dist/public/*.html\");\n\t\t\t//extract necessary bundle scripts to leverage in-app dependencies\n\t\t\tconst scriptGlob = new vscode.RelativePattern(vscode.workspace.workspaceFolders[0], \"*(remove)/node_modules/@storybook/core/dist/public/*.js\");\n\n\t\t\tconsole.log(vscode.Uri.file(fileURLToPath(`/node_modules/@storybook/core/dist/public`)));\n\n\t\t\t//do we need to resolve the Storybook UI script from the /dll/ folder?\n\t\t\t//if extract methods above fail, determine logic to parse out HTML/.js scripts (index 0?);\n\t\t\t//retrieve files with findFiles/relativeFilePath\n\t\t\tconst arrayOfScripts = vscode.workspace.findFiles(distGlob, null, 100);\n\t\t\t//dev check: have we successfully pulled down script files?\n\t\t\t//if so, should we then store them locally, or is there no point?\n\t\t\tif (arrayOfScripts !== undefined){\n\t\t\t\tvscode.window.showInformationMessage(\"Hey, dog: \" + `${arrayOfScripts}`);\n\t\t\t}\n\n\t\t\tvscode.window.showInformationMessage(`\n\t\t\trootPath: ${vscode.workspace.workspaceFolders[0]},\n\t\t\tvscode.Uri: ${vscode.Uri},\n\t\t\tworkspace: ${vscode.workspace},\n\t\t\tdistGlob: ${distGlob.toString()},\n\t\t\thtmlGlob: ${htmlGlob.toString()},\n\t\t\tscriptGlob: ${scriptGlob.toString()}\n\t\t\t`);\n\t\t};\n\n\t\tvscode.window.showInformationMessage(`\n\t\t\trootPath: ${vscode.workspace.workspaceFolders[0].uri.toString()},\\n\n\t\t\tvscode URI parseTest: ${vscode.Uri.parse('file://'+ '/node_modules/@storybook/core/dist/public/index.html')},\\n\n\t\t\tvscode URI parsed w escape: ${vscode.Uri.parse('file://'+ '/node_modules/\\@storybook/core/dist/public/index.html')},\\n\n\t\t\tvscode URI file Test: ${vscode.Uri.file('node_modules/@storybook/core/dist/public/index.html')}\n\t\t\t`);\n\t\t\t\n\t\tconsole.log(`\n\t\trootPath: ${vscode.workspace.workspaceFolders[0]},\n\t\tvscode.Uri: ${vscode.Uri},\n\t\tworkspace: ${vscode.workspace},\n\t\tfileSys: ${vscode.Uri.file(path.join('/'))}`);\n });\n */","module.exports = require(\"child_process\");","module.exports = require(\"fs\");","module.exports = require(\"os\");","module.exports = require(\"path\");","module.exports = require(\"url\");","module.exports = require(\"vscode\");"],"sourceRoot":""} \ No newline at end of file diff --git a/src/extension.ts b/src/extension.ts index 72382b7..4a59499 100644 --- a/src/extension.ts +++ b/src/extension.ts @@ -8,109 +8,119 @@ export function activate(context: vscode.ExtensionContext) { let PORT = 6006; const host = 'localhost'; - + let dependencyFound = false; + let foundSb = false; + let checkedProcesses = false; + //create disposable variable type, registers awaken command & opens webview let disposable = vscode.commands.registerCommand('extension.aesopAwaken', () => { - + //define a path to the root working directory of the user const rootDir = fileURLToPath(vscode.workspace.workspaceFolders[0].uri.toString(true)); //check first to ensure that Storybook has been depended into the current working directory fs.access(path.join(rootDir, '/node_modules/@storybook'), (err) => { - //if the filepath isn't found, show the user what Aesop is reading as the root path - if (err) { vscode.window.showErrorMessage(`Aesop could not find Storybook as a dependency in the active folder, ${rootDir}`); } else { - //check to see if a storybook node process is already running - ps.lookup({ - command: 'node', - psargs: 'ux' - }, (err, resultList) => { - if (err){ + dependencyFound = true; + } + }); + + if (dependencyFound === true && foundSb === false){ + //check to see if a storybook node process is already running + ps.lookup({ + command: 'node', + psargs: 'ux'}, + (err, resultList) => { + if (err){ vscode.window.showErrorMessage(`Failed looking for running Node processes. Error: ${err}`); - } else { - let foundSb = false; - //if the process lookup was able to find running processes, iterate through to review them - resultList.forEach((process) => { + } else { + //if the process lookup was able to find running processes, iterate through to review them + resultList.forEach((process) => { + + // ---> OUTPUT LOGGER <--- // + fs.writeFile(path.join(rootDir, 'YOLO.txt'), `YOLO, fam:\n`, + (err) => {console.log(`Couldn't output process information to YOLO.txt: ${err}`)}); + vscode.window.showInformationMessage('Check YOLO.txt for output information'); + + //check if any running processes are using the start-storybook script + if(process.arguments[0].includes('storybook')){ + foundSb = true; + //stretch goal: check for multiple instances of storybook and reconcile + //if so, extract port number and use that value to populate the webview with that contents + const pFlagIndex = process.arguments.indexOf('-p'); + if (pFlagIndex !== -1){ + PORT = Number(process.arguments[pFlagIndex+1]); + } // ---> OUTPUT LOGGER <--- // - fs.writeFile(path.join(rootDir, 'YOLO.txt'), - `Here is the JSON-stringified version of a process:\n${JSON.stringify(process)}\n`, - (err) => {console.log(`Couldn't output process information to YOLO.txt: ${err}`)}); - vscode.window.showInformationMessage('Check YOLO.txt for output information'); - - //check if any running processes are using the start-storybook script - if(process.arguments[0].includes('storybook')){ - foundSb = true; - //stretch goal: check for multiple instances of storybook and reconcile - //if so, extract port number and use that value to populate the webview with that contents - - const pFlagIndex = process.arguments.indexOf('-p'); - if (pFlagIndex !== -1){ - PORT = Number(process.arguments[pFlagIndex+1]); - } - - // ---> OUTPUT LOGGER <--- // - fs.appendFile(path.join(rootDir, 'YOLO.txt'), `This process matches for 'storybook'search string:\n - PID: ${process.pid}, COMMAND:${process.command}, ARGUMENTS: ${process.arguments}\n`, (err) => {console.log(err)}); - - } - }) - - if (foundSb === false){ - //if no processes match 'storybook', we will have to spin up the storybook server - //starts by extracting the existing storybook script in the package.json - fs.readFile(path.join(rootDir, 'package.json'), (err, data) => { - if (err){ - vscode.window.showErrorMessage(`Does this root folder contain a "package.json" file?`); - } else { - //enter the package.JSON file and retrieve its contents as a string - let packageJSONText = JSON.parse(data.toString()); - let storybookScript = packageJSONText.scripts.storybook; - - // ---> OUTPUT LOGGER <--- // - fs.appendFile(path.join(rootDir, 'YOLO.txt'), `Here is the JSON parsed version:\n - ${packageJSONText.scripts}\n - ${storybookScript}`, (err) => {console.log(err)}); - - //iterate through that text string and parse out important flags - //it is more helpful to split it into an array separated by whitespace to grab these - let retrievedScriptArray = storybookScript.split(' '); - for (let i = 0; i < retrievedScriptArray.length; i++){ - //add flags - if (retrievedScriptArray[i] === '-p'){ - PORT = parseInt(retrievedScriptArray[i+1]); - } - } - } - }) + fs.appendFile(path.join(rootDir, 'YOLO.txt'), `This process matches for 'storybook':\n\n + PID: ${process.pid}, COMMAND:${process.command}, ARGUMENTS: ${process.arguments}\n\n + PORT has been assigned to: ${PORT}`, (err) => {console.log(err)}); + } + }) + checkedProcesses = true; + } + }) + }; + + if (dependencyFound === true && checkedProcesses === true){ + //if no processes match 'storybook', we will have to spin up the storybook server + //starts by extracting the existing storybook script in the package.json + fs.readFile(path.join(rootDir, 'package.json'), (err, data) => { + if (err){ + vscode.window.showErrorMessage(`Aesop is attempting to read ${rootDir}. Is there a package.json file here?`); + } else { + //enter the package.JSON file and retrieve its contents as a string + let packageJSON = JSON.parse(data.toString()); + let storybookScript = packageJSON.scripts.storybook; + + // // ---> OUTPUT LOGGER <--- // + // fs.appendFile(path.join(rootDir, 'YOLO.txt'), `Here is the JSON parsed version:\n + // ${packageJSON.scripts}\n + // ${storybookScript}`, (err) => {console.log(err)}); + + //iterate through that text string and parse out important flags + //it is more helpful to split it into an array separated by whitespace to grab these + let retrievedScriptArray = storybookScript.split(' '); + for (let i = 0; i < retrievedScriptArray.length; i++){ + //add flags as we implement further functionality + if (retrievedScriptArray[i] === '-p'){ + PORT = parseInt(retrievedScriptArray[i+1]); } } - }) - } - }) + + //add --ci tag to existing package.json with an fs function? + //process.scripts.storybook = `${storybookScript} --ci` + } + }); + + //execute Ola's logic to launch the child process, passing rootDir as an options arg + + } //set the extension context equal to "aesop is running" // vscode.commands.executeCommand("setContext", "is-running-aesop", true); //still inside our disposable variable, let's create the webview panel - const panel : vscode.WebviewPanel = vscode.window.createWebviewPanel( + const panel = vscode.window.createWebviewPanel( 'aesop-sb', 'Aesop', vscode.ViewColumn.Two, { enableCommandUris: true, enableScripts: true, - // portMapping: [ - // { webviewPort: PORT, extensionHostPort: PORT} - // ] + portMapping: [ + { webviewPort: PORT, extensionHostPort: PORT} + ] } ); panel.webview.html = - ` + ` + @@ -118,9 +128,10 @@ export function activate(context: vscode.ExtensionContext) { Aesop - - ` + + ` }) context.subscriptions.push(disposable); From 732fb7586ee464edc03c47d2c944ced4df05dc6d Mon Sep 17 00:00:00 2001 From: Keith Cagney Date: Thu, 2 Jan 2020 16:58:59 -0500 Subject: [PATCH 3/3] Just committing some TypeScript declarations to try and problem-solve the instantiation of the Webview at different points; still no working Webview in this edition --- dist/extension.js | 220 ++++++++++++++++++------------- dist/extension.js.map | 2 +- package.json | 70 +++++----- src/extension.ts | 292 +++++++++++++++++++++++++----------------- 4 files changed, 341 insertions(+), 243 deletions(-) diff --git a/dist/extension.js b/dist/extension.js index d16c489..e388aed 100644 --- a/dist/extension.js +++ b/dist/extension.js @@ -1029,13 +1029,14 @@ const url_1 = __webpack_require__(/*! url */ "url"); const path = __webpack_require__(/*! path */ "path"); const fs = __webpack_require__(/*! fs */ "fs"); const ps = __webpack_require__(/*! ps-node */ "./node_modules/ps-node/index.js"); +const child_process = __webpack_require__(/*! child_process */ "child_process"); function activate(context) { let PORT = 6006; const host = 'localhost'; - let dependencyFound = false; - let foundSb = false; //create disposable variable type, registers awaken command & opens webview let disposable = vscode.commands.registerCommand('extension.aesopAwaken', () => { + let checkedProcesses = false; + let foundSb = false; //define a path to the root working directory of the user const rootDir = url_1.fileURLToPath(vscode.workspace.workspaceFolders[0].uri.toString(true)); //check first to ensure that Storybook has been depended into the current working directory @@ -1045,102 +1046,141 @@ function activate(context) { vscode.window.showErrorMessage(`Aesop could not find Storybook as a dependency in the active folder, ${rootDir}`); } else { - dependencyFound = true; - } - }); - if (dependencyFound === true && foundSb === false) { - //check to see if a storybook node process is already running - ps.lookup({ - command: 'node', - psargs: 'ux' - }, (err, resultList) => { - if (err) { - vscode.window.showErrorMessage(`Failed looking for running Node processes. Error: ${err}`); - } - else { - //if the process lookup was able to find running processes, iterate through to review them - resultList.forEach((process) => { - // ---> OUTPUT LOGGER <--- // - fs.writeFile(path.join(rootDir, 'YOLO.txt'), `YOLO, fam:\n\n\n\n`, (err) => { console.log(`Couldn't output process information to YOLO.txt: ${err}`); }); - vscode.window.showInformationMessage('Check YOLO.txt for output information'); - //check if any running processes are using the start-storybook script - if (process.arguments[0].includes('storybook')) { - foundSb = true; - //stretch goal: check for multiple instances of storybook and reconcile - //if so, extract port number and use that value to populate the webview with that contents - const pFlagIndex = process.arguments.indexOf('-p'); - if (pFlagIndex !== -1) { - PORT = Number(process.arguments[pFlagIndex + 1]); - } - // ---> OUTPUT LOGGER <--- // - fs.appendFile(path.join(rootDir, 'YOLO.txt'), `This process matches for 'storybook' search string:\n\n - PID: ${process.pid}, COMMAND:${process.command}, ARGUMENTS: ${process.arguments}\n\nPORT has been assigned to: ${PORT}`, (err) => { console.log(err); }); + vscode.window.showInformationMessage(`Aesop has found your Storybook dependency. Just a moment...`); + if (checkedProcesses === false) { + //check to see if a storybook node process is already running + ps.lookup({ command: 'node', psargs: 'ux' }, (err, resultList) => { + if (err) { + vscode.window.showErrorMessage(`Failed looking for running Node processes. Error: ${err}`); } - }); - } - }); - } - ; - if (dependencyFound === true && foundSb === false) { - //if no processes match 'storybook', we will have to spin up the storybook server - //starts by extracting the existing storybook script in the package.json - fs.readFile(path.join(rootDir, 'package.json'), (err, data) => { - if (err) { - vscode.window.showErrorMessage(`Does this root folder contain a "package.json" file?`); - } - else { - //enter the package.JSON file and retrieve its contents as a string - let packageJSON = JSON.parse(data.toString()); - let storybookScript = packageJSON.scripts.storybook; - // // ---> OUTPUT LOGGER <--- // - // fs.appendFile(path.join(rootDir, 'YOLO.txt'), `Here is the JSON parsed version:\n - // ${packageJSON.scripts}\n - // ${storybookScript}`, (err) => {console.log(err)}); - //iterate through that text string and parse out important flags - //it is more helpful to split it into an array separated by whitespace to grab these - let retrievedScriptArray = storybookScript.split(' '); - for (let i = 0; i < retrievedScriptArray.length; i++) { - //add flags - if (retrievedScriptArray[i] === '-p') { - PORT = parseInt(retrievedScriptArray[i + 1]); + else { + vscode.window.showInformationMessage(`Aesop is checking for a running Storybook...`); + //if the process lookup was able to find running processes, iterate through to review them + resultList.forEach((process) => { + // ---> OUTPUT LOGGER <--- // + fs.writeFile(path.join(rootDir, 'YOLO.txt'), `Attempted launch log:\n`, (err) => { console.log(`Couldn't output process information to YOLO.txt: ${err}`); }); + //check if any running processes are using the start-storybook script + if (process.arguments[0].includes('storybook')) { + //stretch goal: check for multiple instances of storybook and reconcile + //if so, extract port number and use that value to populate the webview with that contents + const pFlagIndex = process.arguments.indexOf('-p'); + if (pFlagIndex !== -1) { + PORT = parseInt(process.arguments[pFlagIndex + 1]); + } + // ---> OUTPUT LOGGER <--- // + fs.appendFile(path.join(rootDir, 'YOLO.txt'), `This process matches for 'storybook':\n + PID: ${process.pid}, COMMAND:${process.command}, ARGUMENTS: ${process.arguments}\n + PORT has been assigned to: ${PORT}`, (err) => { console.log(err); }); + foundSb = true; + } //---> close if process.arguments[0] contains storybook + }); //---> close resultList.forEach() + checkedProcesses = true; + //if no processes match 'storybook', we will have to spin up the storybook server + if (checkedProcesses === true && foundSb === false) { + //starts by extracting the existing storybook port script in the package.json + fs.readFile(path.join(rootDir, 'package.json'), (err, data) => { + if (err) { + vscode.window.showErrorMessage(`Aesop is attempting to read ${rootDir}. Is there a package.json file here?`); + } + else { + //enter the package.JSON file and retrieve its contents as a string + let packageJSON = JSON.parse(data.toString()); + let storybookScript = packageJSON.scripts.storybook; + // ---> OUTPUT LOGGER <--- // + fs.appendFile(path.join(rootDir, 'YOLO.txt'), `Here is the script for "storybook":\n + ${storybookScript}`, (err) => { console.log(err); }); + //iterate through that text string and parse out important flags + //it is more helpful to split it into an array separated by whitespace to grab these + let retrievedScriptArray = storybookScript.split(' '); + for (let i = 0; i < retrievedScriptArray.length; i++) { + //add flags as we implement further functionality + if (retrievedScriptArray[i] === '-p') { + PORT = parseInt(retrievedScriptArray[i + 1]); + fs.appendFile(path.join(rootDir, 'YOLO.txt'), `Port from script":\n${parseInt(retrievedScriptArray[i + 1])}\n + Port at this moment:\n${PORT}\n`, (err) => { console.log(err); }); + break; + } + else if (i === retrievedScriptArray.length - 1) { + fs.appendFile(path.join(rootDir, 'YOLO.txt'), `Script found, but no port flag detected.\n + Port when no port flag found:\n${PORT}\n`, (err) => { console.log(err); }); + //ADD LOGIC TO HANDLE WHEN NO SCRIPT FLAG IS GIVEN + } + } + //add --ci tag to existing package.json with an fs function? + //process.scripts.storybook = `${storybookScript} --ci` + //execute Ola's logic to launch the child process, passing rootDir as an options arg + const runSb = child_process.spawn('npm', ['run', 'storybook']); + vscode.window.showInformationMessage("Done looking. Aesop will now run Storybook."); + runSb.stdout.on('data', (data) => { + console.log(`stdout: ${data}`); + }); + runSb.on('error', function (err) { + console.error(err); + process.exit(1); + }); + //This will make sure the child process is terminated on process exit + runSb.on('close', (code) => { + console.log(`Child process exited with code ${code}`); + }); + } + }); + } //close spin up server + const panel = vscode.window.createWebviewPanel('aesop-sb', 'Aesop', vscode.ViewColumn.Beside, { + enableScripts: true, + localResourceRoots: [vscode.Uri.file(context.extensionPath)] + }); + panel.webview.html = + ` + + + + + Aesop + + + - - - `; - }); + ; //CLOSE else psLookup + }); //close ps LOOKUP + } //close depend found, not checked processes + } //close else statement in fs.access + }); //close fs access + }); //close disposable context.subscriptions.push(disposable); } exports.activate = activate; -; function deactivate() { } exports.deactivate = deactivate; +//set the extension context equal to "aesop is running" +// vscode.commands.executeCommand("setContext", "is-running-aesop", true); +// class AesopPanel implements vscode.WebviewPanel { +// active: true +// // iconPath: /// +// options: {retainContextWhenHidden: true} +// title: string = 'Aesop' +// viewColumn: vscode.ViewColumn.Beside +// visible: true +// webview: vscode.Webview = new AesopWebview +// } +// class AesopWebview implements vscode.Webview{ +// asWebviewUri +// onDidReceiveMessage +// postMessage +// cspSource +// html: string = panelHtml +// options: vscode.WebviewOptions = new AesopWVOptions +// } +// class AesopWVOptions implements vscode.WebviewOptions{ +// enableCommandUris: true +// enableScripts: true +// portMapping: [{ +// webviewPort: number, +// extensionHostPort: number +// }] +// } /* to-do: figure out how to iteratively call sb scripts within our webview diff --git a/dist/extension.js.map b/dist/extension.js.map index ba2b779..79304a3 100644 --- a/dist/extension.js.map +++ b/dist/extension.js.map @@ -1 +1 @@ -{"version":3,"sources":["../webpack/bootstrap",".././node_modules/connected-domain/index.js",".././node_modules/connected-domain/lib/connected-domain.js",".././node_modules/ps-node/index.js",".././node_modules/ps-node/lib/index.js",".././node_modules/table-parser/index.js",".././node_modules/table-parser/lib/index.js",".././src/extension.ts","../external \"child_process\"","../external \"fs\"","../external \"os\"","../external \"path\"","../external \"url\"","../external \"vscode\""],"names":[],"mappings":";;QAAA;QACA;;QAEA;QACA;;QAEA;QACA;QACA;QACA;QACA;QACA;QACA;QACA;QACA;QACA;;QAEA;QACA;;QAEA;QACA;;QAEA;QACA;QACA;;;QAGA;QACA;;QAEA;QACA;;QAEA;QACA;QACA;QACA,0CAA0C,gCAAgC;QAC1E;QACA;;QAEA;QACA;QACA;QACA,wDAAwD,kBAAkB;QAC1E;QACA,iDAAiD,cAAc;QAC/D;;QAEA;QACA;QACA;QACA;QACA;QACA;QACA;QACA;QACA;QACA;QACA;QACA,yCAAyC,iCAAiC;QAC1E,gHAAgH,mBAAmB,EAAE;QACrI;QACA;;QAEA;QACA;QACA;QACA,2BAA2B,0BAA0B,EAAE;QACvD,iCAAiC,eAAe;QAChD;QACA;QACA;;QAEA;QACA,sDAAsD,+DAA+D;;QAErH;QACA;;;QAGA;QACA;;;;;;;;;;;;AClFA,iBAAiB,mBAAO,EAAE,uFAAwB,G;;;;;;;;;;;ACAlD;AACA;AACA;;AAEA;AACA,WAAW,MAAM;AACjB,WAAW,SAAS;AACpB,WAAW,QAAQ;AACnB,YAAY,OAAO,GAAG,YAAY,2BAA2B,aAAa,sBAAsB,EAAE,qCAAqC;AACvI;AACA;;AAEA;;AAEA;AACA;AACA;;AAEA;AACA;AACA;;AAEA;AACA;;AAEA;AACA;AACA;AACA;;AAEA;;AAEA;;AAEA;;AAEA;AACA;;AAEA;AACA;AACA;;AAEA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;;AAEA;AACA;;AAEA;;AAEA;;AAEA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,iBAAiB;;AAEjB;AACA;AACA;AACA;AACA;AACA;AACA;AACA,SAAS;AACT,KAAK;;AAEL;AACA;AACA;AACA;AACA,6BAA6B;AAC7B;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;;AAEA;AACA;AACA;AACA;;AAEA;AACA;;;AAGA;;AAEA;AACA;AACA;AACA;;AAEA;;AAEA;AACA;AACA;;AAEA;AACA;AACA;;AAEA;AACA;AACA;;AAEA;AACA;AACA;AACA,SAAS;;AAET;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA,wBAAwB;AACxB;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;;AAEA;;AAEA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;;AAEA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;;AAEA;AACA;;AAEA;;AAEA;AACA;AACA;AACA,aAAa;;AAEb;;AAEA;AACA;AACA;AACA;;AAEA;AACA,E;;;;;;;;;;;AC/PA,iBAAiB,mBAAO,CAAC,kDAAO;;;;;;;;;;;;ACAhC,mBAAmB,mBAAO,CAAC,oCAAe;AAC1C;AACA,kBAAkB,mBAAO,CAAC,0DAAc;AACxC;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,gBAAgB,mBAAO,CAAC,cAAI;;AAE5B;AACA;AACA,UAAU;AACV,WAAW,SAAS;AACpB,WAAW,SAAS;AACpB,WAAW,YAAY;AACvB,WAAW,SAAS;AACpB;;AAEA;AACA;;AAEA;AACA;AACA;;AAEA;AACA;AACA;;AAEA;AACA;AACA,KAAK;;AAEL;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA,KAAK;;AAEL;;AAEA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA,OAAO;;AAEP;AACA;AACA;;AAEA;AACA,KAAK;;AAEL;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA,KAAK;;AAEL;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA,KAAK;;AAEL;AACA;AACA;AACA;AACA;AACA;AACA;AACA,KAAK;AACL;AACA;;AAEA;AACA;AACA;AACA,WAAW,gBAAgB;AAC3B,WAAW,OAAO;AAClB,WAAW,OAAO;AAClB,WAAW,aAAa;AACxB,WAAW,SAAS;AACpB,WAAW,YAAY;AACvB,WAAW,SAAS;AACpB,YAAY;AACZ;;AAEA;;AAEA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA,KAAK;;AAEL;;;AAGA;AACA;AACA;;AAEA;AACA;AACA;;AAEA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;;AAEA;AACA;AACA;;AAEA;AACA;AACA;;AAEA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA,OAAO;;AAEP;AACA;AACA,GAAG;AACH;;AAEA;AACA;AACA;AACA,WAAW,cAAc;AACzB,WAAW,OAAO;AAClB,WAAW,OAAO;AAClB;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;;AAEA;;AAEA;AACA;AACA;;AAEA;AACA;AACA,GAAG;AACH;AACA;;AAEA;AACA;AACA;;AAEA;AACA,oBAAoB,WAAW;AAC/B;;AAEA;AACA;AACA;AACA,OAAO;AACP;AACA;AACA,OAAO;AACP;AACA;AACA;AACA;AACA,SAAS;AACT;AACA;AACA;AACA,KAAK;AACL;;AAEA;;AAEA;AACA;AACA;AACA,GAAG;AACH;;AAEA;AACA;AACA,WAAW,OAAO;AAClB;;AAEA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA,YAAY;AACZ;;AAEA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;;AAEA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA,OAAO;AACP;AACA,GAAG;;AAEH;AACA;;;;;;;;;;;;ACpSA,iBAAiB,mBAAO,EAAE,6DAAa,G;;;;;;;;;;;ACAvC;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,sBAAsB,mBAAO,CAAC,kEAAkB;AAChD;;AAEA;AACA;AACA;AACA,aAAa;AACb;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA,GAAG;;AAEH;AACA;AACA;;AAEA;AACA;AACA;;AAEA;AACA;;AAEA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,OAAO;AACP;AACA;AACA;AACA;AACA,GAAG;;AAEH;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,GAAG;;AAEH;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,GAAG;;AAEH;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;;AAEA;;AAEA;AACA;AACA;AACA;AACA;AACA,OAAO;;AAEP;AACA;AACA;AACA;AACA;AACA;AACA,SAAS;AACT;AACA;AACA,GAAG;;AAEH;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;;AAEA;AACA;;AAEA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;;AAEA;;AAEA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;;AAEA;AACA,GAAG;;AAEH;AACA;;AAEA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA,GAAG;;AAEH;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA,aAAa;AACb;AACA;AACA;AACA;AACA,yCAAyC;AACzC;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;;AAEA;AACA;;AAEA;;AAEA;;AAEA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;A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","file":"extension.js","sourcesContent":[" \t// The module cache\n \tvar installedModules = {};\n\n \t// The require function\n \tfunction __webpack_require__(moduleId) {\n\n \t\t// Check if module is in cache\n \t\tif(installedModules[moduleId]) {\n \t\t\treturn installedModules[moduleId].exports;\n \t\t}\n \t\t// Create a new module (and put it into the cache)\n \t\tvar module = installedModules[moduleId] = {\n \t\t\ti: moduleId,\n \t\t\tl: false,\n \t\t\texports: {}\n \t\t};\n\n \t\t// Execute the module function\n \t\tmodules[moduleId].call(module.exports, module, module.exports, __webpack_require__);\n\n \t\t// Flag the module as loaded\n \t\tmodule.l = true;\n\n \t\t// Return the exports of the module\n \t\treturn module.exports;\n \t}\n\n\n \t// expose the modules object (__webpack_modules__)\n \t__webpack_require__.m = modules;\n\n \t// expose the module cache\n \t__webpack_require__.c = installedModules;\n\n \t// define getter function for harmony exports\n \t__webpack_require__.d = function(exports, name, getter) {\n \t\tif(!__webpack_require__.o(exports, name)) {\n \t\t\tObject.defineProperty(exports, name, { enumerable: true, get: getter });\n \t\t}\n \t};\n\n \t// define __esModule on exports\n \t__webpack_require__.r = function(exports) {\n \t\tif(typeof Symbol !== 'undefined' && Symbol.toStringTag) {\n \t\t\tObject.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });\n \t\t}\n \t\tObject.defineProperty(exports, '__esModule', { value: true });\n \t};\n\n \t// create a fake namespace object\n \t// mode & 1: value is a module id, require it\n \t// mode & 2: merge all properties of value into the ns\n \t// mode & 4: return value when already ns object\n \t// mode & 8|1: behave like require\n \t__webpack_require__.t = function(value, mode) {\n \t\tif(mode & 1) value = __webpack_require__(value);\n \t\tif(mode & 8) return value;\n \t\tif((mode & 4) && typeof value === 'object' && value && value.__esModule) return value;\n \t\tvar ns = Object.create(null);\n \t\t__webpack_require__.r(ns);\n \t\tObject.defineProperty(ns, 'default', { enumerable: true, value: value });\n \t\tif(mode & 2 && typeof value != 'string') for(var key in value) __webpack_require__.d(ns, key, function(key) { return value[key]; }.bind(null, key));\n \t\treturn ns;\n \t};\n\n \t// getDefaultExport function for compatibility with non-harmony modules\n \t__webpack_require__.n = function(module) {\n \t\tvar getter = module && module.__esModule ?\n \t\t\tfunction getDefault() { return module['default']; } :\n \t\t\tfunction getModuleExports() { return module; };\n \t\t__webpack_require__.d(getter, 'a', getter);\n \t\treturn getter;\n \t};\n\n \t// Object.prototype.hasOwnProperty.call\n \t__webpack_require__.o = function(object, property) { return Object.prototype.hasOwnProperty.call(object, property); };\n\n \t// __webpack_public_path__\n \t__webpack_require__.p = \"\";\n\n\n \t// Load entry module and return exports\n \treturn __webpack_require__(__webpack_require__.s = \"./src/extension.ts\");\n","module.exports = require( './lib/connected-domain' );","/**\n * calculate all the connected domains based on the given two-dimensional array\n */\n\n/**\n * @param {Array} tdArray\n * @param {Function} indicator It receive the raw point data as the first parameter and decide what kind of domain the point belongs to, it should return a string as a domain identifier.\n * @param {Boolean} hardlink If use hard link. Default to false.\n * @return {Object} [{ bounding: { w: 12, h: 19, x: 0, y: 1 }, points: [ { x: 1, y: 2, point: {} } ], identifier: 'blue', domainId: 1 } ]\n */\nmodule.exports = function( tdArray, indicator, hardlink ){\n\n hardlink = hardlink || false;\n\n if( !tdArray ){\n throw new Error( 'tdArray must be provided' );\n }\n\n if( !indicator ){\n throw new Error( 'indicator must be provided' );\n }\n\n // clone 一份数据,因为需要对饮用进行修改,方便执行\n tdArray = JSON.parse( JSON.stringify( tdArray ) );\n\n // Result\n var domains = {};\n var domainUUID = 0;\n var pointsHash = {};\n\n // 遍历数组,划分domain\n\n tdArray.forEach(function( row, y ){\n\n row.forEach(function( colItem, x ){\n\n // get the current point identifier.\n var identifier = indicator( colItem, x, y );\n\n // get neighbours\n // Except for Undefined every data type is valid.\n var neighbours = [];\n\n // top neighbour\n if( tdArray[ y - 1 ] && tdArray[ y - 1 ][ x ] !== undefined ){\n neighbours.push( pointsHash[ x + '_' + ( y - 1 ) ] );\n }\n\n // left neighbour\n if( row[ x - 1 ] !== undefined ){\n neighbours.push( pointsHash[ ( x - 1 ) + '_' + y ] );\n }\n\n // soft link will treat corner link as domain link.\n if( !hardlink ){\n // top left neighbour\n if( tdArray[ y - 1 ] && tdArray[ y - 1 ][ x - 1 ] !== undefined ){\n neighbours.push( pointsHash[ ( x - 1 ) + '_' + ( y - 1 ) ] );\n }\n\n // top right neighbour\n if( tdArray[ y - 1 ] && tdArray[ y - 1 ][ x + 1 ] !== undefined ){\n neighbours.push( pointsHash[ ( x + 1 ) + '_' + ( y - 1 ) ] );\n }\n }\n\n if( neighbours.length ){\n var matched = false;\n\n neighbours.forEach(function( neighbour ){\n\n if( neighbour.identifier == identifier ){\n\n // If the neighbour is the first neighbour has the same identifier\n if( !matched ){\n addPointToDomain( colItem, x, y, neighbour.domainId );\n matched = true;\n }\n\n // If more than one neighbour matched, check if these neighbours belong to the same domain\n // If not, merge these domains since they connects to each other.\n else {\n var colItemPoint = pointsHash[ x + '_' + y ];\n if( neighbour.domainId != colItemPoint.domainId ){\n mergeDomains( neighbour.domainId, colItemPoint.domainId );\n }\n }\n }\n });\n\n if( !matched ){\n addNewDomain( colItem, x, y, identifier );\n }\n }\n else {\n addNewDomain( colItem, x, y, identifier );\n }\n });\n });\n\n // some summary\n var result = {\n domains: [],\n totalDomains: 0,\n groupByIdentifier: {},\n totalIdentifiers: 0\n };\n\n var domainId = null;\n var identifier = null;\n var domain = null;\n for( domainId in domains ){\n domain = domains[ domainId ];\n domain.bounding = calculateBounding( domain.points );\n identifier = domain.identifier;\n\n result.domains.push( domain );\n result.totalDomains++;\n\n if( !( identifier in result.groupByIdentifier ) ){\n result.groupByIdentifier[ identifier ] = [];\n result.totalIdentifiers++;\n }\n\n result.groupByIdentifier[ identifier ].push( domain );\n }\n\n\n function calculateBounding( points ){\n\n var minX = null;\n var minY = null;\n var maxX = null;\n var maxY = null;\n\n points.forEach(function( point ){\n\n if( minX === null || point.x < minX ){\n minX = point.x;\n }\n\n if( minY === null || point.y < minY ){\n minY = point.y;\n }\n\n if( maxX === null || point.x > maxX ){\n maxX = point.x;\n }\n\n if( maxY === null || point.y > maxY ){\n maxY = point.y;\n }\n });\n\n var w = maxX - minX;\n var h = maxY - minY;\n\n return {\n x: minX,\n y: minY,\n w: w,\n h: h\n };\n }\n\n /**\n *\n * @param point\n * @param x\n * @param y\n * @param identifier\n */\n function addNewDomain( point, x, y, identifier ){\n\n var newDomain = {\n identifier: identifier,\n domainId: ++domainUUID,\n bounding: {},\n points: []\n };\n\n var newPoint = {\n value: point,\n x: x,\n y: y,\n identifier: identifier,\n domainId: newDomain.domainId\n };\n\n pointsHash[ x + '_' + y ] = {\n value: point,\n identifier: identifier,\n domainId: newDomain.domainId\n };\n\n newDomain.points.push( newPoint );\n\n domains[ newDomain.domainId ] = newDomain;\n }\n\n /**\n * add a point to a existing domain, and attach properties domainId and identifier to point.\n * @param point\n * @param x\n * @param y\n * @param domainId\n */\n function addPointToDomain( point, x, y, domainId ){\n\n var domain = domains[ domainId ];\n var newPoint = {\n value: point,\n x: x,\n y: y,\n identifier: domain.identifier,\n domainId: domainId\n };\n\n pointsHash[ x + '_' + y ] = {\n value: point,\n identifier: domain.identifier,\n domainId: domainId\n };\n\n domain.points.push( newPoint );\n }\n\n /**\n * 将 domainB 合并到 domainA\n * @param domainAId\n * @param domainBId\n */\n function mergeDomains( domainAId, domainBId ){\n\n var domainA = domains[ domainAId ];\n var domainB = domains[ domainBId ];\n\n if( domainA.identifier == domainB.identifier ){\n // 更新 domainB 的domainId\n\n domainB.domainId = domainA.domainId;\n\n domainB.points.forEach(function( point ){\n point.domainId = domainA.domainId;\n pointsHash[ point.x + '_' + point.y ].domainId = domainA.domainId;\n });\n\n domainA.points = domainA.points.concat( domainB.points );\n\n // 删除domainB\n delete domains[ domainBId ];\n }\n }\n\n return result;\n};","module.exports = require('./lib');\n","var ChildProcess = require('child_process');\nvar IS_WIN = process.platform === 'win32';\nvar TableParser = require('table-parser');\n/**\n * End of line.\n * Basically, the EOL should be:\n * - windows: \\r\\n\n * - *nix: \\n\n * But i'm trying to get every possibilities covered.\n */\nvar EOL = /(\\r\\n)|(\\n\\r)|\\n|\\r/;\nvar SystemEOL = require('os').EOL;\n\n/**\n * Execute child process\n * @type {Function}\n * @param {String[]} args\n * @param {Function} callback\n * @param {Object=null} callback.err\n * @param {Object[]} callback.stdout\n */\n\nvar Exec = module.exports = exports = function (args, callback) {\n var spawn = ChildProcess.spawn;\n\n // on windows, if use ChildProcess.exec(`wmic process get`), the stdout will gives you nothing\n // that's why I use `cmd` instead\n if (IS_WIN) {\n\n var CMD = spawn('cmd');\n var stdout = '';\n var stderr = null;\n\n CMD.stdout.on('data', function (data) {\n stdout += data.toString();\n });\n\n CMD.stderr.on('data', function (data) {\n\n if (stderr === null) {\n stderr = data.toString();\n }\n else {\n stderr += data.toString();\n }\n });\n\n CMD.on('exit', function () {\n\n var beginRow;\n stdout = stdout.split(EOL);\n\n // Find the line index for the titles\n stdout.forEach(function (out, index) {\n if (out && typeof beginRow == 'undefined' && out.indexOf('CommandLine') === 0) {\n beginRow = index;\n }\n });\n\n // get rid of the start (copyright) and the end (current pwd)\n stdout.splice(stdout.length - 1, 1);\n stdout.splice(0, beginRow);\n\n callback(stderr, stdout.join(SystemEOL) || false);\n });\n\n CMD.stdin.write('wmic process get ProcessId,ParentProcessId,CommandLine \\n');\n CMD.stdin.end();\n }\n else {\n if (typeof args === 'string') {\n args = args.split(/\\s+/);\n }\n const child = spawn('ps', args);\n var stdout = '';\n var stderr = null;\n\n child.stdout.on('data', function (data) {\n stdout += data.toString();\n });\n\n child.stderr.on('data', function (data) {\n\n if (stderr === null) {\n stderr = data.toString();\n }\n else {\n stderr += data.toString();\n }\n });\n\n child.on('exit', function () {\n if (stderr) {\n return callback(stderr.toString());\n }\n else {\n callback(null, stdout || false);\n }\n });\n }\n};\n\n/**\n * Query Process: Focus on pid & cmd\n * @param query\n * @param {String|String[]} query.pid\n * @param {String} query.command RegExp String\n * @param {String} query.arguments RegExp String\n * @param {String|array} query.psargs\n * @param {Function} callback\n * @param {Object=null} callback.err\n * @param {Object[]} callback.processList\n * @return {Object}\n */\n\nexports.lookup = function (query, callback) {\n\n /**\n * add 'lx' as default ps arguments, since the default ps output in linux like \"ubuntu\", wont include command arguments\n */\n var exeArgs = query.psargs || ['lx'];\n var filter = {};\n var idList;\n\n // Lookup by PID\n if (query.pid) {\n\n if (Array.isArray(query.pid)) {\n idList = query.pid;\n }\n else {\n idList = [query.pid];\n }\n\n // Cast all PIDs as Strings\n idList = idList.map(function (v) {\n return String(v);\n });\n\n }\n\n\n if (query.command) {\n filter['command'] = new RegExp(query.command, 'i');\n }\n\n if (query.arguments) {\n filter['arguments'] = new RegExp(query.arguments, 'i');\n }\n\n if (query.ppid) {\n filter['ppid'] = new RegExp(query.ppid);\n }\n\n return Exec(exeArgs, function (err, output) {\n if (err) {\n return callback(err);\n }\n else {\n var processList = parseGrid(output);\n var resultList = [];\n\n processList.forEach(function (p) {\n\n var flt;\n var type;\n var result = true;\n\n if (idList && idList.indexOf(String(p.pid)) < 0) {\n return;\n }\n\n for (type in filter) {\n flt = filter[type];\n result = flt.test(p[type]) ? result : false;\n }\n\n if (result) {\n resultList.push(p);\n }\n });\n\n callback(null, resultList);\n }\n });\n};\n\n/**\n * Kill process\n * @param pid\n * @param {Object|String} signal\n * @param {String} signal.signal\n * @param {number} signal.timeout\n * @param next\n */\n\nexports.kill = function( pid, signal, next ){\n //opts are optional\n if(arguments.length == 2 && typeof signal == 'function'){\n next = signal;\n signal = undefined;\n }\n\n var checkTimeoutSeconds = (signal && signal.timeout) || 30;\n\n if (typeof signal === 'object') {\n signal = signal.signal;\n }\n\n try {\n process.kill(pid, signal);\n } catch(e) {\n return next && next(e);\n }\n\n var checkConfident = 0;\n var checkTimeoutTimer = null;\n var checkIsTimeout = false;\n\n function checkKilled(finishCallback) {\n exports.lookup({ pid: pid }, function(err, list) {\n if (checkIsTimeout) return;\n\n if (err) {\n clearTimeout(checkTimeoutTimer);\n finishCallback && finishCallback(err);\n } else if(list.length > 0) {\n checkConfident = (checkConfident - 1) || 0;\n checkKilled(finishCallback);\n } else {\n checkConfident++;\n if (checkConfident === 5) {\n clearTimeout(checkTimeoutTimer);\n finishCallback && finishCallback();\n } else {\n checkKilled(finishCallback);\n }\n }\n });\n }\n\n next && checkKilled(next);\n\n checkTimeoutTimer = next && setTimeout(function() {\n checkIsTimeout = true;\n next(new Error('Kill process timeout'));\n }, checkTimeoutSeconds * 1000);\n};\n\n/**\n * Parse the stdout into readable object.\n * @param {String} output\n */\n\nfunction parseGrid(output) {\n if (!output) {\n return [];\n }\n return formatOutput(TableParser.parse(output));\n}\n\n/**\n * format the structure, extract pid, command, arguments, ppid\n * @param data\n * @return {Array}\n */\n\nfunction formatOutput(data) {\n var formatedData = [];\n data.forEach(function (d) {\n var pid = ( d.PID && d.PID[0] ) || ( d.ProcessId && d.ProcessId[0] ) || undefined;\n var cmd = d.CMD || d.CommandLine || d.COMMAND || undefined;\n var ppid = ( d.PPID && d.PPID[0] ) || ( d.ParentProcessId && d.ParentProcessId[0] ) || undefined;\n\n if (pid && cmd) {\n var command = cmd[0];\n var args = '';\n\n if (cmd.length > 1) {\n args = cmd.slice(1);\n }\n\n formatedData.push({\n pid: pid,\n command: command,\n arguments: args,\n ppid: ppid\n });\n }\n });\n\n return formatedData;\n}\n","module.exports = require( './lib/index' );","/**\n *\n * 1, define the edge ( begin and end ) of every title field\n * 2, parse all the lines except the title line, get all the connected-domains\n * 3, group all the connected-domains vertically overlapped.\n * 4, a domain group belongs to a title field if they vertically overlapped\n * 5, calculate all the edge info through the group domain and title field relations.\n */\nvar ConnectedDomain = require('connected-domain');\nvar EMPTY_EX = /\\s/;\n\n/**\n * The output sting of cmd to parse\n * @param output\n * @returns {Array}\n */\nmodule.exports.parse = function (output) {\n\n // Split into lines\n // Basically, the EOL should be:\n // - windows: \\r\\n\n // - *nix: \\n\n // But i'm trying to get every possibilities covered.\n var linesTmp = output.split(/(\\r\\n)|(\\n\\r)|\\n|\\r/);\n\n // valid lines\n var lines = [];\n // title field info, mapped with filed name.\n var titleInfo = {};\n // the two dimensional array of the lines\n var twoDimArray = [];\n\n // get rid of all the empty lines.\n linesTmp.forEach(function (line) {\n if (line && line.trim()) {\n lines.push(line);\n }\n });\n\n // build title fields edge info\n // build two dimensional array for Connected-Domain to parse.\n lines.forEach(function (line, index) {\n\n // Treat the first line as the title fields line\n if (index == 0) {\n var fields = line.split(/\\s+/);\n\n // record the beginning and ending for each field\n fields.forEach(function (field, idx) {\n\n if (field) {\n var info = titleInfo[field] = {};\n var indexBegin = line.indexOf(field);\n var indexEnd = indexBegin + field.length;\n\n if (idx == 0) {\n info.titleBegin = 0;\n }\n else {\n info.titleBegin = indexBegin;\n }\n\n if (idx == fields.length - 1) {\n info.titleEnd = line.length - 1;\n }\n else {\n info.titleEnd = indexEnd;\n }\n }\n });\n }\n else {\n twoDimArray[index - 1] = line.split('');\n }\n });\n\n // In the connected-domain aspect of view, all the blanks are connected, and all the non-blanks are connected.\n var connectedDomains = ConnectedDomain(twoDimArray, function (value) {\n if (EMPTY_EX.test(value)) {\n return -1;\n }\n else {\n return 1;\n }\n }, true);\n\n // all the connected domains grouped if they are vertically overlapped.\n var valuesDomainsVerticalGroups = [];\n\n // sore the domain list make 'x' in ascending order, it will prevent the situation that:\n // 1, two domains are not overlapped, so two groups are created for them at first\n // 2, another domain is found overlapped with both of the domains at the first step.\n // 3, In this situation the three groups have to be merged, which is complicated to implement.\n //\n // If the list is sorted in this order, this situation can't happen, because:\n // - 1, If two non-overlapped domains A, B ( the \"x\" value of A less than B ) are found first.\n // - 2, Since the list is in 'x' ascending order, the 'x' values of the following domains must larger or equal to the \"x\" of B, which means they will never overlapped with domain A.\n // - 3, So this situation can't happen.\n connectedDomains.domains.sort(function (a, b) {\n return a.bounding.x - b.bounding.x;\n });\n\n // Group domains vertically overlapped.\n connectedDomains.domains.forEach(function (domain) {\n // only handle un-empty domain\n if (domain.identifier === 1) {\n var overlapped = false;\n\n // If overlapped\n valuesDomainsVerticalGroups.forEach(function (group) {\n var bounding = domain.bounding;\n var left = bounding.x;\n var right = bounding.x + bounding.w;\n\n if (overlap(left, right, group.begin, group.end)) {\n\n overlapped = true;\n group.domains.push(domain);\n group.begin = group.begin > left ? left : group.begin;\n group.end = group.end < right ? right : group.end;\n }\n });\n\n // If not overlapped with any group, then create a new group\n if (!overlapped) {\n valuesDomainsVerticalGroups.push({\n begin: domain.bounding.x,\n end: domain.bounding.x + domain.bounding.w,\n domains: [domain]\n });\n }\n }\n });\n\n // connect all the groups to the title fields\n valuesDomainsVerticalGroups.forEach(function (group) {\n var title = null;\n var info = null;\n var overlapped = false;\n\n var minimunLeftDistance = null;\n var nearestLeftTitle = null;\n var distance = null;\n\n for (title in titleInfo) {\n info = titleInfo[title];\n\n /**\n * The calculation below is to find the nearest left title field to the group, in case no overlapped title field found.\n */\n if (group.begin > info.titleBegin) {\n distance = group.begin - info.titleBegin;\n\n if (!nearestLeftTitle || ( distance < minimunLeftDistance )) {\n nearestLeftTitle = title;\n minimunLeftDistance = distance;\n }\n }\n\n if (overlap(group.begin, group.end, info.titleBegin, info.titleEnd)) {\n\n overlapped = true;\n info.titleBegin = info.titleBegin > group.begin ? group.begin : info.titleBegin;\n info.titleEnd = info.titleEnd < group.end ? group.end : info.titleEnd;\n }\n }\n\n // Groups not match any title field belongs to the nearest left title field\n if (!overlapped && nearestLeftTitle) {\n var nearestTitleField = titleInfo[nearestLeftTitle];\n nearestTitleField.titleBegin = nearestTitleField.titleBegin > group.begin ? group.begin : nearestTitleField.titleBegin;\n nearestTitleField.titleEnd = nearestTitleField.titleEnd < group.end ? group.end : nearestTitleField.titleEnd;\n\n }\n });\n\n // The final result\n var result = [];\n\n // Since we have got all the title bounding edges, we can split all the lines into values now\n lines.forEach(function (line, index) {\n // skip the first line\n if (index > 0) {\n\n var lineItem = {};\n var title = null;\n var info = null;\n var value = null;\n for (title in titleInfo) {\n info = titleInfo[title];\n value = line.substring(info.titleBegin, info.titleEnd + 1);\n lineItem[title] = splitValue(value.trim());\n }\n\n result.push(lineItem);\n }\n });\n\n return result;\n};\n\n/**\n * Test if two bounding overlapped vertically\n * @param begin1\n * @param end1\n * @param begin2\n * @param end2\n * @returns {boolean}\n */\nfunction overlap(begin1, end1, begin2, end2) {\n return ( begin1 > begin2 && begin1 < end2 ) || // 2--1--2--1 or 2--1--1--2\n ( end1 > begin2 && end1 < end2 ) || // 1--2--1--2 or 2--1--1--2\n ( begin1 <= begin2 && end1 >= end2 );// 21--12 or 1--2--2--1\n}\n\n/**\n * transform a string value into array. It's not just split(), but also to consider some chunk that wrapped with `\"`, like below:\n * \"C:\\Program Files\\Google\\Chrome\\Application\\chrome.exe\" --type=renderer --lang=zh-CN, `C:\\Program Files\\Google\\Chrome\\Application\\chrome.exe` should be treated as a whole,\n * also, be careful don't be mislead by format like `--name=\"neekey\"`, even more complicated: `--name=\"Neekey Ni\"`\n * so, `\"C:\\Program Files\\Internet Explorer\\iexplore.exe\" --name=\"Jack Neekey\"` should split into:\n * - C:\\Program Files\\Internet Explorer\\iexplore.exe // without `\"`\n * - --name=\"Jack Neekey\" // with `\"`\n */\nfunction splitValue(value) {\n\n var match = value.match(/\"/g);\n\n // If only one \" found, then just ignore it\n if (!match || match.length == 1) {\n return value.split(/\\s+/);\n }\n else {\n var result = [];\n var chunk = null;\n var ifInWrappedChunk = false;\n var ifInPureWrappedChunk = false;\n var quotaCount = 0;\n\n // If the match length is a even, than nothing special, if a odd, ignore the last one.\n var maxQuotaCount = match.length % 2 == 0 ? match.length : match.length - 1;\n\n var previousItem = null;\n var values = value.split('');\n\n values.forEach(function (item, index) {\n\n if (item !== ' ') {\n\n if (item === '\"') {\n // quota chunk begin\n if (ifInWrappedChunk === false && quotaCount <= maxQuotaCount) {\n ifInWrappedChunk = true;\n quotaCount++;\n\n // pure quota chunk begin\n if (previousItem === ' ' || previousItem === null) {\n ifInPureWrappedChunk = true;\n chunk = '';\n }\n // normal continue\n else {\n chunk += item;\n }\n }\n // quota chunk end\n else if (ifInWrappedChunk === true) {\n ifInWrappedChunk = false;\n quotaCount++;\n\n // pure quota chunk end\n if (ifInPureWrappedChunk === true) {\n ifInPureWrappedChunk = false;\n result.push(chunk);\n chunk = null;\n }\n // normal continue\n else {\n chunk += item;\n }\n }\n }\n // normal begin\n else if (ifInWrappedChunk === false && ( previousItem === ' ' || previousItem === null )) {\n chunk = item;\n }\n // normal or quota chunk continue.\n else {\n chunk += item;\n }\n }\n // quota chunk continue, in quota chunk, blank is valid.\n else if (ifInWrappedChunk) {\n chunk += item;\n }\n // if not in quota chunk, them a blank means an end. But make sure chunk is exist, cause that could be blanks at the beginning.\n else if (chunk !== null) {\n result.push(chunk);\n chunk = null;\n }\n\n previousItem = item;\n\n // If this is the last one, but chunk is not end\n if (index == ( values.length - 1 ) && chunk !== null) {\n result.push(chunk);\n chunk = null;\n }\n });\n\n return result;\n }\n}\n","import * as vscode from 'vscode';\nimport { fileURLToPath } from 'url';\nimport * as path from 'path';\nimport * as fs from 'fs';\nimport * as ps from 'ps-node';\n\nexport function activate(context: vscode.ExtensionContext) {\n\n\tlet PORT = 6006;\n\tconst host = 'localhost';\n\tlet dependencyFound = false;\n\tlet foundSb = false;\n\t\n //create disposable variable type, registers awaken command & opens webview\n\tlet disposable = vscode.commands.registerCommand('extension.aesopAwaken', () => {\n\t\t\n\t\t//define a path to the root working directory of the user\n\t\tconst rootDir = fileURLToPath(vscode.workspace.workspaceFolders[0].uri.toString(true));\n\n\t\t//check first to ensure that Storybook has been depended into the current working directory\n\t\tfs.access(path.join(rootDir, '/node_modules/@storybook'), (err) => {\n\t\t\t//if the filepath isn't found, show the user what Aesop is reading as the root path\n\t\t\tif (err) {\n\t\t\t\tvscode.window.showErrorMessage(`Aesop could not find Storybook as a dependency in the active folder, ${rootDir}`);\n\t\t\t}\telse {\n\t\t\t\tdependencyFound = true;\n\t\t\t}\n\t\t});\n\n\t\tif (dependencyFound === true && foundSb === false){\n\t\t\t//check to see if a storybook node process is already running\n\t\t\tps.lookup({\n\t\t\t\tcommand: 'node',\n\t\t\t\tpsargs: 'ux'},\n\t\t\t\t(err, resultList) => {\n\t\t\t\tif (err){\n\t\t\t\t\t\tvscode.window.showErrorMessage(`Failed looking for running Node processes. Error: ${err}`);\n\t\t\t\t} else {\n\t\t\t\t\t//if the process lookup was able to find running processes, iterate through to review them\n\t\t\t\t\tresultList.forEach((process) => {\n\n\t\t\t\t\t\t// ---> OUTPUT LOGGER <--- //\n\t\t\t\t\t\tfs.writeFile(path.join(rootDir, 'YOLO.txt'),\n\t\t\t\t\t\t`YOLO, fam:\\n\\n\\n\\n`,\n\t\t\t\t\t\t(err) => {console.log(`Couldn't output process information to YOLO.txt: ${err}`)});\n\t\t\t\t\t\tvscode.window.showInformationMessage('Check YOLO.txt for output information');\n\n\t\t\t\t\t\t//check if any running processes are using the start-storybook script\n\t\t\t\t\t\tif(process.arguments[0].includes('storybook')){\n\t\t\t\t\t\t\tfoundSb = true;\n\t\t\t\t\t\t\t//stretch goal: check for multiple instances of storybook and reconcile\n\t\t\t\t\t\t\t//if so, extract port number and use that value to populate the webview with that contents\n\t\t\t\t\t\t\n\t\t\t\t\t\t\tconst pFlagIndex = process.arguments.indexOf('-p');\n\t\t\t\t\t\t\tif (pFlagIndex !== -1){\n\t\t\t\t\t\t\t\tPORT = Number(process.arguments[pFlagIndex+1]);\n\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\t// ---> OUTPUT LOGGER <--- //\n\t\t\t\t\t\t\tfs.appendFile(path.join(rootDir, 'YOLO.txt'), `This process matches for 'storybook' search string:\\n\\n\n\t\t\t\t\t\t\tPID: ${process.pid}, COMMAND:${process.command}, ARGUMENTS: ${process.arguments}\\n\\nPORT has been assigned to: ${PORT}`, (err) => {console.log(err)});\n\t\t\t\t\t\t}\n\t\t\t\t\t})\n\t\t\t\t}\n\t\t\t})\n\t\t};\n\n\t\tif (dependencyFound === true && foundSb === false){\n\t\t\t//if no processes match 'storybook', we will have to spin up the storybook server\n\t\t\t//starts by extracting the existing storybook script in the package.json\n\t\t\tfs.readFile(path.join(rootDir, 'package.json'), (err, data) => {\n\t\t\t\tif (err){\n\t\t\t\t\tvscode.window.showErrorMessage(`Does this root folder contain a \"package.json\" file?`);\n\t\t\t\t}\telse {\n\t\t\t\t\t//enter the package.JSON file and retrieve its contents as a string\n\t\t\t\t\tlet packageJSON = JSON.parse(data.toString());\n\t\t\t\t\tlet storybookScript = packageJSON.scripts.storybook;\n\n\t\t\t\t\t// // ---> OUTPUT LOGGER <--- //\n\t\t\t\t\t// fs.appendFile(path.join(rootDir, 'YOLO.txt'), `Here is the JSON parsed version:\\n\n\t\t\t\t\t// ${packageJSON.scripts}\\n\n\t\t\t\t\t// ${storybookScript}`, (err) => {console.log(err)});\n\n\t\t\t\t\t//iterate through that text string and parse out important flags\n\t\t\t\t\t//it is more helpful to split it into an array separated by whitespace to grab these\n\t\t\t\t\tlet retrievedScriptArray = storybookScript.split(' ');\n\t\t\t\t\tfor (let i = 0; i < retrievedScriptArray.length; i++){\n\t\t\t\t\t\t//add flags\n\t\t\t\t\t\tif (retrievedScriptArray[i] === '-p'){\n\t\t\t\t\t\t\tPORT = parseInt(retrievedScriptArray[i+1]);\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t});\n\n\t\t\t//execute Ola's logic to launch the child process, passing rootDir as an options arg\n\n\t\t}\n\n\t\t//set the extension context equal to \"aesop is running\"\n\t\t// vscode.commands.executeCommand(\"setContext\", \"is-running-aesop\", true);\n\n\t\t//still inside our disposable variable, let's create the webview panel\n\t\tconst panel = vscode.window.createWebviewPanel(\n\t\t\t'aesop-sb',\n\t\t\t'Aesop',\n\t\t\tvscode.ViewColumn.Two,\n\t\t\t{\n\t\t\t\tenableCommandUris: true,\n\t\t\t\tenableScripts: true,\n\t\t\t\tportMapping: [\n\t\t\t\t\t{ webviewPort: PORT, extensionHostPort: PORT}\n\t\t\t\t]\n\t\t\t}\n\t\t);\n\n\t\tpanel.webview.html =\n\t\t`\n\t\t\n\t\t\t\n\t\t\t\t\n\t\t\t\t\t\n\t\t\t\t\t\n\t\t\t\t\tAesop\n\t\t\t\t\n\t\t\t\t\n\t\t\t\t\t\n\t\t\t\t\n\t\t\t\n\t\t`\n\t})\n\n\tcontext.subscriptions.push(disposable);\n};\n\nexport function deactivate() {\n\t\n}\n\n/*\nto-do:\n\tfigure out how to iteratively call sb scripts within our webview\n\twebview messages / scripts to reload\n\tfigure out how to use a tsx rule in webpack to execute scripts\n\tsignal babel to interpret this block as tsx, e.g. something like: //@tsx babel//\n\n\n\t\n\t\t\t\t\t\tvscode.tasks.registerTaskProvider('runStorybook', {\n\t\t\t\t\t\t\t\t\t\t\t\tprovideTasks(token?: vscode.CancellationToken) {\n\t\t\t\t\t\t\t\t\t\t\t\t\t\treturn [\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tnew vscode.Task({type: 'runStorybook'}, vscode.TaskScope.Workspace,\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\"Aesop Chronicle\", \"aesop\", new vscode.ShellExecution(`npm run storybook --ci`))\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t];\n\t\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\tresolveTask(task: vscode.Task, token?: vscode.CancellationToken) {\n\t\t\t\t\t\t\t\t\t\t\t\t\t\treturn task;\n\t\t\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t\t\t});\n\n\t\t\t\t\t\t\t\t\t\t\t//define the script text to execute to the virtual terminal instance\n\t\t\t\t\t\t\t\t\t\t\tconst bootScript = `storybook --ci`;\n\t\t\t\t\t\t\t\t\t\t\tconst bootStorybook = new vscode.ProcessExecution(bootScript, {cwd: rootDir});\n\n\t\t\t\t\t\t\t\t\t\t\t//now create a virtual terminal and execute our special npm script for it\n\t\t\t\t\t\t\t\t\t\t\t//this first requires creating an eventEmitter that will fire that script\n\t\t\t\t\t\t\t\t\t\t\tconst scriptEmitter = new vscode.EventEmitter();\n\t\t\t\t\t\t\t\n\t\t\t\t\t\t\t\t\t\t\t//we also define a slave process Pseudoterminal (allowing Aesop to control the terminal)\n\t\t\t\t\t\t\t\t\t\t\tconst pty: vscode.Pseudoterminal = {\n\t\t\t\t\t\t\t\t\t\t\t\tonDidWrite: scriptEmitter.event,\n\t\t\t\t\t\t\t\t\t\t\t\topen: () =>\tscriptEmitter.fire(bootScript),\n\t\t\t\t\t\t\t\t\t\t\t\tclose: () => {},\n\t\t\t\t\t\t\t\t\t\t\t\thandleInput: data => new vscode.ShellExecution(data)\n\t\t\t\t\t\t\t\t\t\t\t};\n\n\t\t\t\t\t\t\t\t\t\t\t//should this just be an active terminal/shellExecution?\n\t\t\t\t\t\t\t\t\t\t\tconst virtualTerminal = vscode.window.createTerminal({name: 'sb-runner', pty});\n\n//THIS WORKS, but we have no access to the DOM inside our webview//\n\t//now let's read SB's outputted index.html file, and parse out what we need\n\t\tfs.readFile(path.join(rootDir, '/node_modules/@storybook/core/dist/public/index.html'), (err, data) => {\n\t\t\tif (err) console.error(err);\n\t\t\telse {\n\t\t\t\tlet pulledHTML = data.toString();\n\t\t\t\tlet targetPoint = pulledHTML.indexOf('');\n\t\t\t\tlet firstHalf = pulledHTML.slice(0, targetPoint);\n\t\t\t\tlet secondHalf = pulledHTML.slice(targetPoint);\n\t\t\t\tpulledHTML = firstHalf.concat(payloadScript).concat(secondHalf);\n\t\t\t\tfs.writeFile(path.join(rootDir, '/node_modules/@storybook/core/dist/public/index.html'), pulledHTML, (err) => {\n\t\t\t\t\tif (err) console.error(err);\n\t\t\t\t\telse {\n\t\t\t\t\t\tvscode.window.showInformationMessage('Successfully injected script');\n\t\t\t\t\t};\n\t\t\t\t});\n\t\t\t}\n\t\t});\n\n\t//declare an empty array (of strings) to push our scripts to during the next part\n\t\tconst scriptArray : Array = [];\n\t\t//define a path to the root working directory of the user\n\t\tconst rootDir = fileURLToPath(vscode.workspace.workspaceFolders[0].uri.toString(true));\n\t\t//now let's read SB's outputted index.html file, and parse out what we need\n\t\tfs.readFile(path.join(rootDir, '/node_modules/@storybook/core/dist/public/index.html'), (err, data) => {\n\t\t\tif (err) console.error(err);\n\t\t\telse {\n\t\t\t\t//if we've read the HTML file, take its contents and stringify it\n\t\t\t\tlet outputFile = data.toString();\n\t\t\t\t// this log shows what our eventual permutations would look like as we carve out the scripts\n\t\t\t\t// vscode.window.showWarningMessage(`what's in it: ${outputFile.slice(outputFile.indexOf('')+6, outputFile.indexOf(''))} \\n`)\n\t\t\t\t//split out the body section of the retrieved html file\n\t\t\t\toutputFile = outputFile.slice(outputFile.indexOf('')+6, outputFile.indexOf(''));\n\t\t\t\tvscode.window.showWarningMessage(`${outputFile} \\n`)\n\n\t\t\t\t//this loop will peel out all the scripts so long as there are any to rip out\n\t\t\t\twhile (outputFile.includes(`\" tags behind\n\t\t\t\t\tlet temp = outputFile.slice(outputFile.indexOf(``));\n\t\t\t\t\tscriptArray.push(temp);\n\t\t\t\t\toutputFile = outputFile.slice(outputFile.indexOf(`\">`)+10);\n\t\t\t\t}\n\t\t\t};\n\t\t});\n\n
\n
\t\n\t
\n\t\n\t\n\t\n
\n\n\tdisposable = vscode.commands.registerCommand('extension.getStories', () => {\n\t\tbuild a command that retrieves Storybook files on startup\n\t\tcan be executed later if Storybook server is spun up after the extension opens\n\t\t\n\t\talso register this command at startup to crawl the file path\n\t\t${vscode.commands.executeCommand('extension.getStories')}\n\t\tvscode.window.showInformationMessage('Aesop is reading from your Storybook.');\n\n\t\tdefine a path to SB webpack bundle outputs (in user workspace /node_modules/ folder)\n\t\tif (vscode.workspace.workspaceFolders[0] !== undefined){\n\t\t\tconst distGlob = new vscode.RelativePattern(vscode.workspace.workspaceFolders[0], \"**(remove)/node_modules/@storybook/core/dist/public\");\n\t\t\t//instantiate a watcher to listen for fs path changes (e.g. file creation/update)\n\t\t\t//bools = options for ignoreCreateEvents?, ignoreChangeEvents?, ignoreDeleteEvents?\t\n\t\t\tconst observer = vscode.workspace.createFileSystemWatcher(distGlob, false, false, false);\n\t\t\t// observer.onDidChange = //resolve//;\t\t// observer.onDidCreate = //resolve//;\n\t\t\t//extract index.html file that outputs into SB's preview pane\n\t\t\tconst htmlGlob = new vscode.RelativePattern(vscode.workspace.workspaceFolders[0], \"*(remove)/node_modules/@storybook/core/dist/public/*.html\");\n\t\t\t//extract necessary bundle scripts to leverage in-app dependencies\n\t\t\tconst scriptGlob = new vscode.RelativePattern(vscode.workspace.workspaceFolders[0], \"*(remove)/node_modules/@storybook/core/dist/public/*.js\");\n\n\t\t\tconsole.log(vscode.Uri.file(fileURLToPath(`/node_modules/@storybook/core/dist/public`)));\n\n\t\t\t//do we need to resolve the Storybook UI script from the /dll/ folder?\n\t\t\t//if extract methods above fail, determine logic to parse out HTML/.js scripts (index 0?);\n\t\t\t//retrieve files with findFiles/relativeFilePath\n\t\t\tconst arrayOfScripts = vscode.workspace.findFiles(distGlob, null, 100);\n\t\t\t//dev check: have we successfully pulled down script files?\n\t\t\t//if so, should we then store them locally, or is there no point?\n\t\t\tif (arrayOfScripts !== undefined){\n\t\t\t\tvscode.window.showInformationMessage(\"Hey, dog: \" + `${arrayOfScripts}`);\n\t\t\t}\n\n\t\t\tvscode.window.showInformationMessage(`\n\t\t\trootPath: ${vscode.workspace.workspaceFolders[0]},\n\t\t\tvscode.Uri: ${vscode.Uri},\n\t\t\tworkspace: ${vscode.workspace},\n\t\t\tdistGlob: ${distGlob.toString()},\n\t\t\thtmlGlob: ${htmlGlob.toString()},\n\t\t\tscriptGlob: ${scriptGlob.toString()}\n\t\t\t`);\n\t\t};\n\n\t\tvscode.window.showInformationMessage(`\n\t\t\trootPath: ${vscode.workspace.workspaceFolders[0].uri.toString()},\\n\n\t\t\tvscode URI parseTest: ${vscode.Uri.parse('file://'+ '/node_modules/@storybook/core/dist/public/index.html')},\\n\n\t\t\tvscode URI parsed w escape: ${vscode.Uri.parse('file://'+ '/node_modules/\\@storybook/core/dist/public/index.html')},\\n\n\t\t\tvscode URI file Test: ${vscode.Uri.file('node_modules/@storybook/core/dist/public/index.html')}\n\t\t\t`);\n\t\t\t\n\t\tconsole.log(`\n\t\trootPath: ${vscode.workspace.workspaceFolders[0]},\n\t\tvscode.Uri: ${vscode.Uri},\n\t\tworkspace: ${vscode.workspace},\n\t\tfileSys: ${vscode.Uri.file(path.join('/'))}`);\n });\n */","module.exports = require(\"child_process\");","module.exports = require(\"fs\");","module.exports = require(\"os\");","module.exports = require(\"path\");","module.exports = require(\"url\");","module.exports = require(\"vscode\");"],"sourceRoot":""} \ No newline at end of file +{"version":3,"sources":["../webpack/bootstrap",".././node_modules/connected-domain/index.js",".././node_modules/connected-domain/lib/connected-domain.js",".././node_modules/ps-node/index.js",".././node_modules/ps-node/lib/index.js",".././node_modules/table-parser/index.js",".././node_modules/table-parser/lib/index.js",".././src/extension.ts","../external \"child_process\"","../external \"fs\"","../external \"os\"","../external \"path\"","../external \"url\"","../external \"vscode\""],"names":[],"mappings":";;QAAA;QACA;;QAEA;QACA;;QAEA;QACA;QACA;QACA;QACA;QACA;QACA;QACA;QACA;QACA;;QAEA;QACA;;QAEA;QACA;;QAEA;QACA;QACA;;;QAGA;QACA;;QAEA;QACA;;QAEA;QACA;QACA;QACA,0CAA0C,gCAAgC;QAC1E;QACA;;QAEA;QACA;QACA;QACA,wDAAwD,kBAAkB;QAC1E;QACA,iDAAiD,cAAc;QAC/D;;QAEA;QACA;QACA;QACA;QACA;QACA;QACA;QACA;QACA;QACA;QACA;QACA,yCAAyC,iCAAiC;QAC1E,gHAAgH,mBAAmB,EAAE;QACrI;QACA;;QAEA;QACA;QACA;QACA,2BAA2B,0BAA0B,EAAE;QACvD,iCAAiC,eAAe;QAChD;QACA;QACA;;QAEA;QACA,sDAAsD,+DAA+D;;QAErH;QACA;;;QAGA;QACA;;;;;;;;;;;;AClFA,iBAAiB,mBAAO,EAAE,uFAAwB,G;;;;;;;;;;;ACAlD;AACA;AACA;;AAEA;AACA,WAAW,MAAM;AACjB,WAAW,SAAS;AACpB,WAAW,QAAQ;AACnB,YAAY,OAAO,GAAG,YAAY,2BAA2B,aAAa,sBAAsB,EAAE,qCAAqC;AACvI;AACA;;AAEA;;AAEA;AACA;AACA;;AAEA;AACA;AACA;;AAEA;AACA;;AAEA;AACA;AACA;AACA;;AAEA;;AAEA;;AAEA;;AAEA;AACA;;AAEA;AACA;AACA;;AAEA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;;AAEA;AACA;;AAEA;;AAEA;;AAEA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,iBAAiB;;AAEjB;AACA;AACA;AACA;AACA;AACA;AACA;AACA,SAAS;AACT,KAAK;;AAEL;AACA;AACA;AACA;AACA,6BAA6B;AAC7B;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;;AAEA;AACA;AACA;AACA;;AAEA;AACA;;;AAGA;;AAEA;AACA;AACA;AACA;;AAEA;;AAEA;AACA;AACA;;AAEA;AACA;AACA;;AAEA;AACA;AACA;;AAEA;AACA;AACA;AACA,SAAS;;AAET;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA,wBAAwB;AACxB;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;;AAEA;;AAEA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;;AAEA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;;AAEA;AACA;;AAEA;;AAEA;AACA;AACA;AACA,aAAa;;AAEb;;AAEA;AACA;AACA;AACA;;AAEA;AACA,E;;;;;;;;;;;AC/PA,iBAAiB,mBAAO,CAAC,kDAAO;;;;;;;;;;;;ACAhC,mBAAmB,mBAAO,CAAC,oCAAe;AAC1C;AACA,kBAAkB,mBAAO,CAAC,0DAAc;AACxC;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,gBAAgB,mBAAO,CAAC,cAAI;;AAE5B;AACA;AACA,UAAU;AACV,WAAW,SAAS;AACpB,WAAW,SAAS;AACpB,WAAW,YAAY;AACvB,WAAW,SAAS;AACpB;;AAEA;AACA;;AAEA;AACA;AACA;;AAEA;AACA;AACA;;AAEA;AACA;AACA,KAAK;;AAEL;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA,KAAK;;AAEL;;AAEA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA,OAAO;;AAEP;AACA;AACA;;AAEA;AACA,KAAK;;AAEL;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA,KAAK;;AAEL;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA,KAAK;;AAEL;AACA;AACA;AACA;AACA;AACA;AACA;AACA,KAAK;AACL;AACA;;AAEA;AACA;AACA;AACA,WAAW,gBAAgB;AAC3B,WAAW,OAAO;AAClB,WAAW,OAAO;AAClB,WAAW,aAAa;AACxB,WAAW,SAAS;AACpB,WAAW,YAAY;AACvB,WAAW,SAAS;AACpB,YAAY;AACZ;;AAEA;;AAEA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA,KAAK;;AAEL;;;AAGA;AACA;AACA;;AAEA;AACA;AACA;;AAEA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;;AAEA;AACA;AACA;;AAEA;AACA;AACA;;AAEA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA,OAAO;;AAEP;AACA;AACA,GAAG;AACH;;AAEA;AACA;AACA;AACA,WAAW,cAAc;AACzB,WAAW,OAAO;AAClB,WAAW,OAAO;AAClB;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;;AAEA;;AAEA;AACA;AACA;;AAEA;AACA;AACA,GAAG;AACH;AACA;;AAEA;AACA;AACA;;AAEA;AACA,oBAAoB,WAAW;AAC/B;;AAEA;AACA;AACA;AACA,OAAO;AACP;AACA;AACA,OAAO;AACP;AACA;AACA;AACA;AACA,SAAS;AACT;AACA;AACA;AACA,KAAK;AACL;;AAEA;;AAEA;AACA;AACA;AACA,GAAG;AACH;;AAEA;AACA;AACA,WAAW,OAAO;AAClB;;AAEA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA,YAAY;AACZ;;AAEA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;;AAEA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA,OAAO;AACP;AACA,GAAG;;AAEH;AACA;;;;;;;;;;;;ACpSA,iBAAiB,mBAAO,EAAE,6DAAa,G;;;;;;;;;;;ACAvC;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,sBAAsB,mBAAO,CAAC,kEAAkB;AAChD;;AAEA;AACA;AACA;AACA,aAAa;AACb;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA,GAAG;;AAEH;AACA;AACA;;AAEA;AACA;AACA;;AAEA;AACA;;AAEA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,OAAO;AACP;AACA;AACA;AACA;AACA,GAAG;;AAEH;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,GAAG;;AAEH;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,GAAG;;AAEH;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;;AAEA;;AAEA;AACA;AACA;AACA;AACA;AACA,OAAO;;AAEP;AACA;AACA;AACA;AACA;AACA;AACA,SAAS;AACT;AACA;AACA,GAAG;;AAEH;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;;AAEA;AACA;;AAEA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;;AAEA;;AAEA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;;AAEA;AACA,GAAG;;AAEH;AACA;;AAEA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA,GAAG;;AAEH;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA,aAAa;AACb;AACA;AACA;AACA;AACA,yCAAyC;AACzC;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;;AAEA;AACA;;AAEA;;AAEA;;AAEA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;A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","file":"extension.js","sourcesContent":[" \t// The module cache\n \tvar installedModules = {};\n\n \t// The require function\n \tfunction __webpack_require__(moduleId) {\n\n \t\t// Check if module is in cache\n \t\tif(installedModules[moduleId]) {\n \t\t\treturn installedModules[moduleId].exports;\n \t\t}\n \t\t// Create a new module (and put it into the cache)\n \t\tvar module = installedModules[moduleId] = {\n \t\t\ti: moduleId,\n \t\t\tl: false,\n \t\t\texports: {}\n \t\t};\n\n \t\t// Execute the module function\n \t\tmodules[moduleId].call(module.exports, module, module.exports, __webpack_require__);\n\n \t\t// Flag the module as loaded\n \t\tmodule.l = true;\n\n \t\t// Return the exports of the module\n \t\treturn module.exports;\n \t}\n\n\n \t// expose the modules object (__webpack_modules__)\n \t__webpack_require__.m = modules;\n\n \t// expose the module cache\n \t__webpack_require__.c = installedModules;\n\n \t// define getter function for harmony exports\n \t__webpack_require__.d = function(exports, name, getter) {\n \t\tif(!__webpack_require__.o(exports, name)) {\n \t\t\tObject.defineProperty(exports, name, { enumerable: true, get: getter });\n \t\t}\n \t};\n\n \t// define __esModule on exports\n \t__webpack_require__.r = function(exports) {\n \t\tif(typeof Symbol !== 'undefined' && Symbol.toStringTag) {\n \t\t\tObject.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });\n \t\t}\n \t\tObject.defineProperty(exports, '__esModule', { value: true });\n \t};\n\n \t// create a fake namespace object\n \t// mode & 1: value is a module id, require it\n \t// mode & 2: merge all properties of value into the ns\n \t// mode & 4: return value when already ns object\n \t// mode & 8|1: behave like require\n \t__webpack_require__.t = function(value, mode) {\n \t\tif(mode & 1) value = __webpack_require__(value);\n \t\tif(mode & 8) return value;\n \t\tif((mode & 4) && typeof value === 'object' && value && value.__esModule) return value;\n \t\tvar ns = Object.create(null);\n \t\t__webpack_require__.r(ns);\n \t\tObject.defineProperty(ns, 'default', { enumerable: true, value: value });\n \t\tif(mode & 2 && typeof value != 'string') for(var key in value) __webpack_require__.d(ns, key, function(key) { return value[key]; }.bind(null, key));\n \t\treturn ns;\n \t};\n\n \t// getDefaultExport function for compatibility with non-harmony modules\n \t__webpack_require__.n = function(module) {\n \t\tvar getter = module && module.__esModule ?\n \t\t\tfunction getDefault() { return module['default']; } :\n \t\t\tfunction getModuleExports() { return module; };\n \t\t__webpack_require__.d(getter, 'a', getter);\n \t\treturn getter;\n \t};\n\n \t// Object.prototype.hasOwnProperty.call\n \t__webpack_require__.o = function(object, property) { return Object.prototype.hasOwnProperty.call(object, property); };\n\n \t// __webpack_public_path__\n \t__webpack_require__.p = \"\";\n\n\n \t// Load entry module and return exports\n \treturn __webpack_require__(__webpack_require__.s = \"./src/extension.ts\");\n","module.exports = require( './lib/connected-domain' );","/**\n * calculate all the connected domains based on the given two-dimensional array\n */\n\n/**\n * @param {Array} tdArray\n * @param {Function} indicator It receive the raw point data as the first parameter and decide what kind of domain the point belongs to, it should return a string as a domain identifier.\n * @param {Boolean} hardlink If use hard link. Default to false.\n * @return {Object} [{ bounding: { w: 12, h: 19, x: 0, y: 1 }, points: [ { x: 1, y: 2, point: {} } ], identifier: 'blue', domainId: 1 } ]\n */\nmodule.exports = function( tdArray, indicator, hardlink ){\n\n hardlink = hardlink || false;\n\n if( !tdArray ){\n throw new Error( 'tdArray must be provided' );\n }\n\n if( !indicator ){\n throw new Error( 'indicator must be provided' );\n }\n\n // clone 一份数据,因为需要对饮用进行修改,方便执行\n tdArray = JSON.parse( JSON.stringify( tdArray ) );\n\n // Result\n var domains = {};\n var domainUUID = 0;\n var pointsHash = {};\n\n // 遍历数组,划分domain\n\n tdArray.forEach(function( row, y ){\n\n row.forEach(function( colItem, x ){\n\n // get the current point identifier.\n var identifier = indicator( colItem, x, y );\n\n // get neighbours\n // Except for Undefined every data type is valid.\n var neighbours = [];\n\n // top neighbour\n if( tdArray[ y - 1 ] && tdArray[ y - 1 ][ x ] !== undefined ){\n neighbours.push( pointsHash[ x + '_' + ( y - 1 ) ] );\n }\n\n // left neighbour\n if( row[ x - 1 ] !== undefined ){\n neighbours.push( pointsHash[ ( x - 1 ) + '_' + y ] );\n }\n\n // soft link will treat corner link as domain link.\n if( !hardlink ){\n // top left neighbour\n if( tdArray[ y - 1 ] && tdArray[ y - 1 ][ x - 1 ] !== undefined ){\n neighbours.push( pointsHash[ ( x - 1 ) + '_' + ( y - 1 ) ] );\n }\n\n // top right neighbour\n if( tdArray[ y - 1 ] && tdArray[ y - 1 ][ x + 1 ] !== undefined ){\n neighbours.push( pointsHash[ ( x + 1 ) + '_' + ( y - 1 ) ] );\n }\n }\n\n if( neighbours.length ){\n var matched = false;\n\n neighbours.forEach(function( neighbour ){\n\n if( neighbour.identifier == identifier ){\n\n // If the neighbour is the first neighbour has the same identifier\n if( !matched ){\n addPointToDomain( colItem, x, y, neighbour.domainId );\n matched = true;\n }\n\n // If more than one neighbour matched, check if these neighbours belong to the same domain\n // If not, merge these domains since they connects to each other.\n else {\n var colItemPoint = pointsHash[ x + '_' + y ];\n if( neighbour.domainId != colItemPoint.domainId ){\n mergeDomains( neighbour.domainId, colItemPoint.domainId );\n }\n }\n }\n });\n\n if( !matched ){\n addNewDomain( colItem, x, y, identifier );\n }\n }\n else {\n addNewDomain( colItem, x, y, identifier );\n }\n });\n });\n\n // some summary\n var result = {\n domains: [],\n totalDomains: 0,\n groupByIdentifier: {},\n totalIdentifiers: 0\n };\n\n var domainId = null;\n var identifier = null;\n var domain = null;\n for( domainId in domains ){\n domain = domains[ domainId ];\n domain.bounding = calculateBounding( domain.points );\n identifier = domain.identifier;\n\n result.domains.push( domain );\n result.totalDomains++;\n\n if( !( identifier in result.groupByIdentifier ) ){\n result.groupByIdentifier[ identifier ] = [];\n result.totalIdentifiers++;\n }\n\n result.groupByIdentifier[ identifier ].push( domain );\n }\n\n\n function calculateBounding( points ){\n\n var minX = null;\n var minY = null;\n var maxX = null;\n var maxY = null;\n\n points.forEach(function( point ){\n\n if( minX === null || point.x < minX ){\n minX = point.x;\n }\n\n if( minY === null || point.y < minY ){\n minY = point.y;\n }\n\n if( maxX === null || point.x > maxX ){\n maxX = point.x;\n }\n\n if( maxY === null || point.y > maxY ){\n maxY = point.y;\n }\n });\n\n var w = maxX - minX;\n var h = maxY - minY;\n\n return {\n x: minX,\n y: minY,\n w: w,\n h: h\n };\n }\n\n /**\n *\n * @param point\n * @param x\n * @param y\n * @param identifier\n */\n function addNewDomain( point, x, y, identifier ){\n\n var newDomain = {\n identifier: identifier,\n domainId: ++domainUUID,\n bounding: {},\n points: []\n };\n\n var newPoint = {\n value: point,\n x: x,\n y: y,\n identifier: identifier,\n domainId: newDomain.domainId\n };\n\n pointsHash[ x + '_' + y ] = {\n value: point,\n identifier: identifier,\n domainId: newDomain.domainId\n };\n\n newDomain.points.push( newPoint );\n\n domains[ newDomain.domainId ] = newDomain;\n }\n\n /**\n * add a point to a existing domain, and attach properties domainId and identifier to point.\n * @param point\n * @param x\n * @param y\n * @param domainId\n */\n function addPointToDomain( point, x, y, domainId ){\n\n var domain = domains[ domainId ];\n var newPoint = {\n value: point,\n x: x,\n y: y,\n identifier: domain.identifier,\n domainId: domainId\n };\n\n pointsHash[ x + '_' + y ] = {\n value: point,\n identifier: domain.identifier,\n domainId: domainId\n };\n\n domain.points.push( newPoint );\n }\n\n /**\n * 将 domainB 合并到 domainA\n * @param domainAId\n * @param domainBId\n */\n function mergeDomains( domainAId, domainBId ){\n\n var domainA = domains[ domainAId ];\n var domainB = domains[ domainBId ];\n\n if( domainA.identifier == domainB.identifier ){\n // 更新 domainB 的domainId\n\n domainB.domainId = domainA.domainId;\n\n domainB.points.forEach(function( point ){\n point.domainId = domainA.domainId;\n pointsHash[ point.x + '_' + point.y ].domainId = domainA.domainId;\n });\n\n domainA.points = domainA.points.concat( domainB.points );\n\n // 删除domainB\n delete domains[ domainBId ];\n }\n }\n\n return result;\n};","module.exports = require('./lib');\n","var ChildProcess = require('child_process');\nvar IS_WIN = process.platform === 'win32';\nvar TableParser = require('table-parser');\n/**\n * End of line.\n * Basically, the EOL should be:\n * - windows: \\r\\n\n * - *nix: \\n\n * But i'm trying to get every possibilities covered.\n */\nvar EOL = /(\\r\\n)|(\\n\\r)|\\n|\\r/;\nvar SystemEOL = require('os').EOL;\n\n/**\n * Execute child process\n * @type {Function}\n * @param {String[]} args\n * @param {Function} callback\n * @param {Object=null} callback.err\n * @param {Object[]} callback.stdout\n */\n\nvar Exec = module.exports = exports = function (args, callback) {\n var spawn = ChildProcess.spawn;\n\n // on windows, if use ChildProcess.exec(`wmic process get`), the stdout will gives you nothing\n // that's why I use `cmd` instead\n if (IS_WIN) {\n\n var CMD = spawn('cmd');\n var stdout = '';\n var stderr = null;\n\n CMD.stdout.on('data', function (data) {\n stdout += data.toString();\n });\n\n CMD.stderr.on('data', function (data) {\n\n if (stderr === null) {\n stderr = data.toString();\n }\n else {\n stderr += data.toString();\n }\n });\n\n CMD.on('exit', function () {\n\n var beginRow;\n stdout = stdout.split(EOL);\n\n // Find the line index for the titles\n stdout.forEach(function (out, index) {\n if (out && typeof beginRow == 'undefined' && out.indexOf('CommandLine') === 0) {\n beginRow = index;\n }\n });\n\n // get rid of the start (copyright) and the end (current pwd)\n stdout.splice(stdout.length - 1, 1);\n stdout.splice(0, beginRow);\n\n callback(stderr, stdout.join(SystemEOL) || false);\n });\n\n CMD.stdin.write('wmic process get ProcessId,ParentProcessId,CommandLine \\n');\n CMD.stdin.end();\n }\n else {\n if (typeof args === 'string') {\n args = args.split(/\\s+/);\n }\n const child = spawn('ps', args);\n var stdout = '';\n var stderr = null;\n\n child.stdout.on('data', function (data) {\n stdout += data.toString();\n });\n\n child.stderr.on('data', function (data) {\n\n if (stderr === null) {\n stderr = data.toString();\n }\n else {\n stderr += data.toString();\n }\n });\n\n child.on('exit', function () {\n if (stderr) {\n return callback(stderr.toString());\n }\n else {\n callback(null, stdout || false);\n }\n });\n }\n};\n\n/**\n * Query Process: Focus on pid & cmd\n * @param query\n * @param {String|String[]} query.pid\n * @param {String} query.command RegExp String\n * @param {String} query.arguments RegExp String\n * @param {String|array} query.psargs\n * @param {Function} callback\n * @param {Object=null} callback.err\n * @param {Object[]} callback.processList\n * @return {Object}\n */\n\nexports.lookup = function (query, callback) {\n\n /**\n * add 'lx' as default ps arguments, since the default ps output in linux like \"ubuntu\", wont include command arguments\n */\n var exeArgs = query.psargs || ['lx'];\n var filter = {};\n var idList;\n\n // Lookup by PID\n if (query.pid) {\n\n if (Array.isArray(query.pid)) {\n idList = query.pid;\n }\n else {\n idList = [query.pid];\n }\n\n // Cast all PIDs as Strings\n idList = idList.map(function (v) {\n return String(v);\n });\n\n }\n\n\n if (query.command) {\n filter['command'] = new RegExp(query.command, 'i');\n }\n\n if (query.arguments) {\n filter['arguments'] = new RegExp(query.arguments, 'i');\n }\n\n if (query.ppid) {\n filter['ppid'] = new RegExp(query.ppid);\n }\n\n return Exec(exeArgs, function (err, output) {\n if (err) {\n return callback(err);\n }\n else {\n var processList = parseGrid(output);\n var resultList = [];\n\n processList.forEach(function (p) {\n\n var flt;\n var type;\n var result = true;\n\n if (idList && idList.indexOf(String(p.pid)) < 0) {\n return;\n }\n\n for (type in filter) {\n flt = filter[type];\n result = flt.test(p[type]) ? result : false;\n }\n\n if (result) {\n resultList.push(p);\n }\n });\n\n callback(null, resultList);\n }\n });\n};\n\n/**\n * Kill process\n * @param pid\n * @param {Object|String} signal\n * @param {String} signal.signal\n * @param {number} signal.timeout\n * @param next\n */\n\nexports.kill = function( pid, signal, next ){\n //opts are optional\n if(arguments.length == 2 && typeof signal == 'function'){\n next = signal;\n signal = undefined;\n }\n\n var checkTimeoutSeconds = (signal && signal.timeout) || 30;\n\n if (typeof signal === 'object') {\n signal = signal.signal;\n }\n\n try {\n process.kill(pid, signal);\n } catch(e) {\n return next && next(e);\n }\n\n var checkConfident = 0;\n var checkTimeoutTimer = null;\n var checkIsTimeout = false;\n\n function checkKilled(finishCallback) {\n exports.lookup({ pid: pid }, function(err, list) {\n if (checkIsTimeout) return;\n\n if (err) {\n clearTimeout(checkTimeoutTimer);\n finishCallback && finishCallback(err);\n } else if(list.length > 0) {\n checkConfident = (checkConfident - 1) || 0;\n checkKilled(finishCallback);\n } else {\n checkConfident++;\n if (checkConfident === 5) {\n clearTimeout(checkTimeoutTimer);\n finishCallback && finishCallback();\n } else {\n checkKilled(finishCallback);\n }\n }\n });\n }\n\n next && checkKilled(next);\n\n checkTimeoutTimer = next && setTimeout(function() {\n checkIsTimeout = true;\n next(new Error('Kill process timeout'));\n }, checkTimeoutSeconds * 1000);\n};\n\n/**\n * Parse the stdout into readable object.\n * @param {String} output\n */\n\nfunction parseGrid(output) {\n if (!output) {\n return [];\n }\n return formatOutput(TableParser.parse(output));\n}\n\n/**\n * format the structure, extract pid, command, arguments, ppid\n * @param data\n * @return {Array}\n */\n\nfunction formatOutput(data) {\n var formatedData = [];\n data.forEach(function (d) {\n var pid = ( d.PID && d.PID[0] ) || ( d.ProcessId && d.ProcessId[0] ) || undefined;\n var cmd = d.CMD || d.CommandLine || d.COMMAND || undefined;\n var ppid = ( d.PPID && d.PPID[0] ) || ( d.ParentProcessId && d.ParentProcessId[0] ) || undefined;\n\n if (pid && cmd) {\n var command = cmd[0];\n var args = '';\n\n if (cmd.length > 1) {\n args = cmd.slice(1);\n }\n\n formatedData.push({\n pid: pid,\n command: command,\n arguments: args,\n ppid: ppid\n });\n }\n });\n\n return formatedData;\n}\n","module.exports = require( './lib/index' );","/**\n *\n * 1, define the edge ( begin and end ) of every title field\n * 2, parse all the lines except the title line, get all the connected-domains\n * 3, group all the connected-domains vertically overlapped.\n * 4, a domain group belongs to a title field if they vertically overlapped\n * 5, calculate all the edge info through the group domain and title field relations.\n */\nvar ConnectedDomain = require('connected-domain');\nvar EMPTY_EX = /\\s/;\n\n/**\n * The output sting of cmd to parse\n * @param output\n * @returns {Array}\n */\nmodule.exports.parse = function (output) {\n\n // Split into lines\n // Basically, the EOL should be:\n // - windows: \\r\\n\n // - *nix: \\n\n // But i'm trying to get every possibilities covered.\n var linesTmp = output.split(/(\\r\\n)|(\\n\\r)|\\n|\\r/);\n\n // valid lines\n var lines = [];\n // title field info, mapped with filed name.\n var titleInfo = {};\n // the two dimensional array of the lines\n var twoDimArray = [];\n\n // get rid of all the empty lines.\n linesTmp.forEach(function (line) {\n if (line && line.trim()) {\n lines.push(line);\n }\n });\n\n // build title fields edge info\n // build two dimensional array for Connected-Domain to parse.\n lines.forEach(function (line, index) {\n\n // Treat the first line as the title fields line\n if (index == 0) {\n var fields = line.split(/\\s+/);\n\n // record the beginning and ending for each field\n fields.forEach(function (field, idx) {\n\n if (field) {\n var info = titleInfo[field] = {};\n var indexBegin = line.indexOf(field);\n var indexEnd = indexBegin + field.length;\n\n if (idx == 0) {\n info.titleBegin = 0;\n }\n else {\n info.titleBegin = indexBegin;\n }\n\n if (idx == fields.length - 1) {\n info.titleEnd = line.length - 1;\n }\n else {\n info.titleEnd = indexEnd;\n }\n }\n });\n }\n else {\n twoDimArray[index - 1] = line.split('');\n }\n });\n\n // In the connected-domain aspect of view, all the blanks are connected, and all the non-blanks are connected.\n var connectedDomains = ConnectedDomain(twoDimArray, function (value) {\n if (EMPTY_EX.test(value)) {\n return -1;\n }\n else {\n return 1;\n }\n }, true);\n\n // all the connected domains grouped if they are vertically overlapped.\n var valuesDomainsVerticalGroups = [];\n\n // sore the domain list make 'x' in ascending order, it will prevent the situation that:\n // 1, two domains are not overlapped, so two groups are created for them at first\n // 2, another domain is found overlapped with both of the domains at the first step.\n // 3, In this situation the three groups have to be merged, which is complicated to implement.\n //\n // If the list is sorted in this order, this situation can't happen, because:\n // - 1, If two non-overlapped domains A, B ( the \"x\" value of A less than B ) are found first.\n // - 2, Since the list is in 'x' ascending order, the 'x' values of the following domains must larger or equal to the \"x\" of B, which means they will never overlapped with domain A.\n // - 3, So this situation can't happen.\n connectedDomains.domains.sort(function (a, b) {\n return a.bounding.x - b.bounding.x;\n });\n\n // Group domains vertically overlapped.\n connectedDomains.domains.forEach(function (domain) {\n // only handle un-empty domain\n if (domain.identifier === 1) {\n var overlapped = false;\n\n // If overlapped\n valuesDomainsVerticalGroups.forEach(function (group) {\n var bounding = domain.bounding;\n var left = bounding.x;\n var right = bounding.x + bounding.w;\n\n if (overlap(left, right, group.begin, group.end)) {\n\n overlapped = true;\n group.domains.push(domain);\n group.begin = group.begin > left ? left : group.begin;\n group.end = group.end < right ? right : group.end;\n }\n });\n\n // If not overlapped with any group, then create a new group\n if (!overlapped) {\n valuesDomainsVerticalGroups.push({\n begin: domain.bounding.x,\n end: domain.bounding.x + domain.bounding.w,\n domains: [domain]\n });\n }\n }\n });\n\n // connect all the groups to the title fields\n valuesDomainsVerticalGroups.forEach(function (group) {\n var title = null;\n var info = null;\n var overlapped = false;\n\n var minimunLeftDistance = null;\n var nearestLeftTitle = null;\n var distance = null;\n\n for (title in titleInfo) {\n info = titleInfo[title];\n\n /**\n * The calculation below is to find the nearest left title field to the group, in case no overlapped title field found.\n */\n if (group.begin > info.titleBegin) {\n distance = group.begin - info.titleBegin;\n\n if (!nearestLeftTitle || ( distance < minimunLeftDistance )) {\n nearestLeftTitle = title;\n minimunLeftDistance = distance;\n }\n }\n\n if (overlap(group.begin, group.end, info.titleBegin, info.titleEnd)) {\n\n overlapped = true;\n info.titleBegin = info.titleBegin > group.begin ? group.begin : info.titleBegin;\n info.titleEnd = info.titleEnd < group.end ? group.end : info.titleEnd;\n }\n }\n\n // Groups not match any title field belongs to the nearest left title field\n if (!overlapped && nearestLeftTitle) {\n var nearestTitleField = titleInfo[nearestLeftTitle];\n nearestTitleField.titleBegin = nearestTitleField.titleBegin > group.begin ? group.begin : nearestTitleField.titleBegin;\n nearestTitleField.titleEnd = nearestTitleField.titleEnd < group.end ? group.end : nearestTitleField.titleEnd;\n\n }\n });\n\n // The final result\n var result = [];\n\n // Since we have got all the title bounding edges, we can split all the lines into values now\n lines.forEach(function (line, index) {\n // skip the first line\n if (index > 0) {\n\n var lineItem = {};\n var title = null;\n var info = null;\n var value = null;\n for (title in titleInfo) {\n info = titleInfo[title];\n value = line.substring(info.titleBegin, info.titleEnd + 1);\n lineItem[title] = splitValue(value.trim());\n }\n\n result.push(lineItem);\n }\n });\n\n return result;\n};\n\n/**\n * Test if two bounding overlapped vertically\n * @param begin1\n * @param end1\n * @param begin2\n * @param end2\n * @returns {boolean}\n */\nfunction overlap(begin1, end1, begin2, end2) {\n return ( begin1 > begin2 && begin1 < end2 ) || // 2--1--2--1 or 2--1--1--2\n ( end1 > begin2 && end1 < end2 ) || // 1--2--1--2 or 2--1--1--2\n ( begin1 <= begin2 && end1 >= end2 );// 21--12 or 1--2--2--1\n}\n\n/**\n * transform a string value into array. It's not just split(), but also to consider some chunk that wrapped with `\"`, like below:\n * \"C:\\Program Files\\Google\\Chrome\\Application\\chrome.exe\" --type=renderer --lang=zh-CN, `C:\\Program Files\\Google\\Chrome\\Application\\chrome.exe` should be treated as a whole,\n * also, be careful don't be mislead by format like `--name=\"neekey\"`, even more complicated: `--name=\"Neekey Ni\"`\n * so, `\"C:\\Program Files\\Internet Explorer\\iexplore.exe\" --name=\"Jack Neekey\"` should split into:\n * - C:\\Program Files\\Internet Explorer\\iexplore.exe // without `\"`\n * - --name=\"Jack Neekey\" // with `\"`\n */\nfunction splitValue(value) {\n\n var match = value.match(/\"/g);\n\n // If only one \" found, then just ignore it\n if (!match || match.length == 1) {\n return value.split(/\\s+/);\n }\n else {\n var result = [];\n var chunk = null;\n var ifInWrappedChunk = false;\n var ifInPureWrappedChunk = false;\n var quotaCount = 0;\n\n // If the match length is a even, than nothing special, if a odd, ignore the last one.\n var maxQuotaCount = match.length % 2 == 0 ? match.length : match.length - 1;\n\n var previousItem = null;\n var values = value.split('');\n\n values.forEach(function (item, index) {\n\n if (item !== ' ') {\n\n if (item === '\"') {\n // quota chunk begin\n if (ifInWrappedChunk === false && quotaCount <= maxQuotaCount) {\n ifInWrappedChunk = true;\n quotaCount++;\n\n // pure quota chunk begin\n if (previousItem === ' ' || previousItem === null) {\n ifInPureWrappedChunk = true;\n chunk = '';\n }\n // normal continue\n else {\n chunk += item;\n }\n }\n // quota chunk end\n else if (ifInWrappedChunk === true) {\n ifInWrappedChunk = false;\n quotaCount++;\n\n // pure quota chunk end\n if (ifInPureWrappedChunk === true) {\n ifInPureWrappedChunk = false;\n result.push(chunk);\n chunk = null;\n }\n // normal continue\n else {\n chunk += item;\n }\n }\n }\n // normal begin\n else if (ifInWrappedChunk === false && ( previousItem === ' ' || previousItem === null )) {\n chunk = item;\n }\n // normal or quota chunk continue.\n else {\n chunk += item;\n }\n }\n // quota chunk continue, in quota chunk, blank is valid.\n else if (ifInWrappedChunk) {\n chunk += item;\n }\n // if not in quota chunk, them a blank means an end. But make sure chunk is exist, cause that could be blanks at the beginning.\n else if (chunk !== null) {\n result.push(chunk);\n chunk = null;\n }\n\n previousItem = item;\n\n // If this is the last one, but chunk is not end\n if (index == ( values.length - 1 ) && chunk !== null) {\n result.push(chunk);\n chunk = null;\n }\n });\n\n return result;\n }\n}\n","import * as vscode from 'vscode';\nimport { fileURLToPath } from 'url';\nimport * as path from 'path';\nimport * as fs from 'fs';\nimport * as ps from 'ps-node';\nimport * as child_process from 'child_process';\n\nexport function activate(context: vscode.ExtensionContext) {\n\n\tlet PORT = 6006;\n\tconst host = 'localhost';\n\n //create disposable variable type, registers awaken command & opens webview\n\tlet disposable = vscode.commands.registerCommand('extension.aesopAwaken', () => {\n\t\tlet checkedProcesses : Boolean = false;\n\t\tlet foundSb : Boolean = false;\n\t\t\t\n\t\t//define a path to the root working directory of the user\n\t\tconst rootDir : string = fileURLToPath(vscode.workspace.workspaceFolders[0].uri.toString(true));\n\n\t\t//check first to ensure that Storybook has been depended into the current working directory\n\t\tfs.access(path.join(rootDir, '/node_modules/@storybook'), (err) => {\n\t\t\t//if the filepath isn't found, show the user what Aesop is reading as the root path\n\t\t\tif (err) {\n\t\t\t\tvscode.window.showErrorMessage(`Aesop could not find Storybook as a dependency in the active folder, ${rootDir}`);\n\t\t\t}\telse {\n\t\t\t\tvscode.window.showInformationMessage(`Aesop has found your Storybook dependency. Just a moment...`);\n\n\t\t\t\tif (checkedProcesses === false){\n\t\t\t\t\t//check to see if a storybook node process is already running\n\t\t\t\t\tps.lookup({command: 'node', psargs: 'ux'}, (err, resultList) => {\n\t\t\t\t\t\tif (err){\n\t\t\t\t\t\t\tvscode.window.showErrorMessage(`Failed looking for running Node processes. Error: ${err}`);\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\tvscode.window.showInformationMessage(`Aesop is checking for a running Storybook...`);\n\n\t\t\t\t\t\t\t//if the process lookup was able to find running processes, iterate through to review them\n\t\t\t\t\t\t\tresultList.forEach((process) => {\n\n\t\t\t\t\t\t\t\t// ---> OUTPUT LOGGER <--- //\n\t\t\t\t\t\t\t\tfs.writeFile(path.join(rootDir, 'YOLO.txt'), `Attempted launch log:\\n`,\n\t\t\t\t\t\t\t\t(err) => {console.log(`Couldn't output process information to YOLO.txt: ${err}`)});\n\t\t\n\t\t\t\t\t\t\t\t//check if any running processes are using the start-storybook script\n\t\t\t\t\t\t\t\tif(process.arguments[0].includes('storybook')){\n\n\t\t\t\t\t\t\t\t\t//stretch goal: check for multiple instances of storybook and reconcile\n\t\t\t\t\t\t\t\t\t//if so, extract port number and use that value to populate the webview with that contents\n\t\t\t\t\t\t\t\t\tconst pFlagIndex = process.arguments.indexOf('-p');\n\t\t\t\t\t\t\t\t\tif (pFlagIndex !== -1){\n\t\t\t\t\t\t\t\t\t\tPORT = parseInt(process.arguments[pFlagIndex+1]);\n\t\t\t\t\t\t\t\t\t}\n\t\t\n\t\t\t\t\t\t\t\t\t// ---> OUTPUT LOGGER <--- //\n\t\t\t\t\t\t\t\t\tfs.appendFile(path.join(rootDir, 'YOLO.txt'), `This process matches for 'storybook':\\n\n\t\t\t\t\t\t\t\t\tPID: ${process.pid}, COMMAND:${process.command}, ARGUMENTS: ${process.arguments}\\n\n\t\t\t\t\t\t\t\t\tPORT has been assigned to: ${PORT}`, (err) => {console.log(err)});\n\n\t\t\t\t\t\t\t\t\tfoundSb = true;\n\n\t\t\t\t\t\t\t\t}//---> close if process.arguments[0] contains storybook\n\t\t\t\t\t\t\t}) //---> close resultList.forEach()\n\n\t\t\t\t\t\t\tcheckedProcesses = true;\n\t\t\t\t\t\t\n\t\t\t\t\t\t\t//if no processes match 'storybook', we will have to spin up the storybook server\n\t\t\t\t\t\t\tif (checkedProcesses === true && foundSb === false){\n\t\t\t\t\t\t\t\t\n\t\t\t\t\t\t\t\t//starts by extracting the existing storybook port script in the package.json\n\t\t\t\t\t\t\t\tfs.readFile(path.join(rootDir, 'package.json'), (err, data) => {\n\t\t\t\t\t\t\t\t\tif (err){\n\t\t\t\t\t\t\t\t\t\tvscode.window.showErrorMessage(`Aesop is attempting to read ${rootDir}. Is there a package.json file here?`);\n\t\t\t\t\t\t\t\t\t}\telse {\n\t\t\t\t\t\t\t\t\t\t//enter the package.JSON file and retrieve its contents as a string\n\t\t\t\t\t\t\t\t\t\tlet packageJSON = JSON.parse(data.toString());\n\t\t\t\t\t\t\t\t\t\tlet storybookScript = packageJSON.scripts.storybook;\n\t\t\t\t\t\n\t\t\t\t\t\t\t\t\t\t// ---> OUTPUT LOGGER <--- //\n\t\t\t\t\t\t\t\t\t\tfs.appendFile(path.join(rootDir, 'YOLO.txt'), `Here is the script for \"storybook\":\\n\n\t\t\t\t\t\t\t\t\t\t${storybookScript}`, (err) => {console.log(err)});\n\t\t\t\t\t\n\t\t\t\t\t\t\t\t\t\t//iterate through that text string and parse out important flags\n\t\t\t\t\t\t\t\t\t\t//it is more helpful to split it into an array separated by whitespace to grab these\n\t\t\t\t\t\t\t\t\t\tlet retrievedScriptArray = storybookScript.split(' ');\n\t\t\t\t\t\t\t\t\t\tfor (let i = 0; i < retrievedScriptArray.length; i++){\n\t\t\t\t\t\t\t\t\t\t\t//add flags as we implement further functionality\n\t\t\t\t\t\t\t\t\t\t\tif (retrievedScriptArray[i] === '-p'){\n\t\t\t\t\t\t\t\t\t\t\t\tPORT = parseInt(retrievedScriptArray[i+1]);\n\t\t\t\t\t\t\t\t\t\t\t\tfs.appendFile(path.join(rootDir, 'YOLO.txt'), `Port from script\":\\n${parseInt(retrievedScriptArray[i+1])}\\n\n\t\t\t\t\t\t\t\t\t\t\t\tPort at this moment:\\n${PORT}\\n`, (err) => {console.log(err)});\n\t\t\t\t\t\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t\t\t\t\t\t} else if (i === retrievedScriptArray.length-1){\n\t\t\t\t\t\t\t\t\t\t\t\tfs.appendFile(path.join(rootDir, 'YOLO.txt'), `Script found, but no port flag detected.\\n\n\t\t\t\t\t\t\t\t\t\t\t\tPort when no port flag found:\\n${PORT}\\n`, (err) => {console.log(err)});\n\t\t\t\t\t\t\t\t\t\t\t\t//ADD LOGIC TO HANDLE WHEN NO SCRIPT FLAG IS GIVEN\n\t\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t\t//add --ci tag to existing package.json with an fs function?\n\t\t\t\t\t\t\t\t\t\t//process.scripts.storybook = `${storybookScript} --ci`\n\n\t\t\t\t\t\t\t\t\t\t//execute Ola's logic to launch the child process, passing rootDir as an options arg\n\t\t\t\t\t\t\t\t\t\tconst runSb = child_process.spawn('npm', ['run', 'storybook']);\n\t\t\t\t\t\t\t\t\t\tvscode.window.showInformationMessage(\"Done looking. Aesop will now run Storybook.\");\n\t\t\t\t\t\t\t\t\t\t\n\t\t\t\t\t\t\t\t\t\trunSb.stdout.on('data', (data) => {\n\t\t\t\t\t\t\t\t\t\t\tconsole.log(`stdout: ${data}`);\n\t\t\t\t\t\t\t\t\t\t})\n\t\t\t\t\t\t\t\t\t\t\n\t\t\t\t\t\t\t\t\t\trunSb.on('error', function(err) {\n\t\t\t\t\t\t\t\t\t\t\tconsole.error(err);\n\t\t\t\t\t\t\t\t\t\t\tprocess.exit(1);\n\t\t\t\t\t\t\t\t\t\t})\n\t\t\t\t\t\t\t\t\t\t\n\t\t\t\t\t\t\t\t\t\t//This will make sure the child process is terminated on process exit\n\t\t\t\t\t\t\t\t\t\trunSb.on('close', (code) => {\n\t\t\t\t\t\t\t\t\t\t\tconsole.log(`Child process exited with code ${code}`)\n\t\t\t\t\t\t\t\t\t\t})\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t})\n\t\t\t\t\t\t\t} //close spin up server\n\t\t\t\t\t\t\t\n\t\t\t\t\t\t\tconst panel = vscode.window.createWebviewPanel(\n\t\t\t\t\t\t\t\t'aesop-sb',\n\t\t\t\t\t\t\t\t'Aesop',\n\t\t\t\t\t\t\t\tvscode.ViewColumn.Beside,\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\tenableScripts: true,\n\t\t\t\t\t\t\t\t\tlocalResourceRoots: [vscode.Uri.file(context.extensionPath)]\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t);\n\t\t\t\t\t\t\t\n\t\t\t\t\t\t\tpanel.webview.html =\n\t\t\t\t\t\t\t\t`\n\t\t\t\t\t\t\t\t\n\t\t\t\t\t\t\t\t\t\n\t\t\t\t\t\t\t\t\t\t\n\t\t\t\t\t\t\t\t\t\t\n\t\t\t\t\t\t\t\t\t\tAesop\n\t\t\t\t\t\t\t\t\t\n\t\t\t\t\t\t\t\t\t\n\t\t\t\t\t\t\t\t\t\t\n\t\t\t\t\t\t\t\t\t\n\t\t\t\t\t\t\t\t`\n\t\t\t\t\t\t}; //CLOSE else psLookup\n\t\t\t\t\t}); //close ps LOOKUP\n\t\t\t\t} //close depend found, not checked processes\n\t\t\t}//close else statement in fs.access\n\t\t}) //close fs access\n\t}); //close disposable\n\n\tcontext.subscriptions.push(disposable);\n}\n\nexport function deactivate() {\n}\n\n//set the extension context equal to \"aesop is running\"\n// vscode.commands.executeCommand(\"setContext\", \"is-running-aesop\", true);\n\n\t\t// class AesopPanel implements vscode.WebviewPanel {\n\t\t// \tactive: true\n\t\t// \t// iconPath: ///\n\t\t// \toptions: {retainContextWhenHidden: true}\n\t\t// \ttitle: string = 'Aesop'\n\t\t// \tviewColumn: vscode.ViewColumn.Beside\n\t\t// \tvisible: true\n\t\t// \twebview: vscode.Webview = new AesopWebview\n\t\t// }\n\n\t\t// class AesopWebview implements vscode.Webview{\n\t\t// \t\tasWebviewUri\n\t\t// \t\tonDidReceiveMessage\n\t\t// \t\tpostMessage\n\t\t// \t\tcspSource\n\t\t// \t\thtml: string = panelHtml\n\t\t// \t\toptions: vscode.WebviewOptions = new AesopWVOptions\n\t\t// }\n\n\t\t// class AesopWVOptions implements vscode.WebviewOptions{\n\t\t// \tenableCommandUris: true\n\t\t// \tenableScripts: true\n\t\t// \tportMapping: [{\n\t\t// \t\twebviewPort: number,\n\t\t// \t\textensionHostPort: number\n\t\t// \t}]\n\t\t// }\n\n/*\nto-do:\n\tfigure out how to iteratively call sb scripts within our webview\n\twebview messages / scripts to reload\n\tfigure out how to use a tsx rule in webpack to execute scripts\n\tsignal babel to interpret this block as tsx, e.g. something like: //@tsx babel//\n\n\n\t\n\t\t\t\t\t\tvscode.tasks.registerTaskProvider('runStorybook', {\n\t\t\t\t\t\t\t\t\t\t\t\tprovideTasks(token?: vscode.CancellationToken) {\n\t\t\t\t\t\t\t\t\t\t\t\t\t\treturn [\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tnew vscode.Task({type: 'runStorybook'}, vscode.TaskScope.Workspace,\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\"Aesop Chronicle\", \"aesop\", new vscode.ShellExecution(`npm run storybook --ci`))\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t];\n\t\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\tresolveTask(task: vscode.Task, token?: vscode.CancellationToken) {\n\t\t\t\t\t\t\t\t\t\t\t\t\t\treturn task;\n\t\t\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t\t\t});\n\n\t\t\t\t\t\t\t\t\t\t\t//define the script text to execute to the virtual terminal instance\n\t\t\t\t\t\t\t\t\t\t\tconst bootScript = `storybook --ci`;\n\t\t\t\t\t\t\t\t\t\t\tconst bootStorybook = new vscode.ProcessExecution(bootScript, {cwd: rootDir});\n\n\t\t\t\t\t\t\t\t\t\t\t//now create a virtual terminal and execute our special npm script for it\n\t\t\t\t\t\t\t\t\t\t\t//this first requires creating an eventEmitter that will fire that script\n\t\t\t\t\t\t\t\t\t\t\tconst scriptEmitter = new vscode.EventEmitter();\n\t\t\t\t\t\t\t\n\t\t\t\t\t\t\t\t\t\t\t//we also define a slave process Pseudoterminal (allowing Aesop to control the terminal)\n\t\t\t\t\t\t\t\t\t\t\tconst pty: vscode.Pseudoterminal = {\n\t\t\t\t\t\t\t\t\t\t\t\tonDidWrite: scriptEmitter.event,\n\t\t\t\t\t\t\t\t\t\t\t\topen: () =>\tscriptEmitter.fire(bootScript),\n\t\t\t\t\t\t\t\t\t\t\t\tclose: () => {},\n\t\t\t\t\t\t\t\t\t\t\t\thandleInput: data => new vscode.ShellExecution(data)\n\t\t\t\t\t\t\t\t\t\t\t};\n\n\t\t\t\t\t\t\t\t\t\t\t//should this just be an active terminal/shellExecution?\n\t\t\t\t\t\t\t\t\t\t\tconst virtualTerminal = vscode.window.createTerminal({name: 'sb-runner', pty});\n\n//THIS WORKS, but we have no access to the DOM inside our webview//\n\t//now let's read SB's outputted index.html file, and parse out what we need\n\t\tfs.readFile(path.join(rootDir, '/node_modules/@storybook/core/dist/public/index.html'), (err, data) => {\n\t\t\tif (err) console.error(err);\n\t\t\telse {\n\t\t\t\tlet pulledHTML = data.toString();\n\t\t\t\tlet targetPoint = pulledHTML.indexOf('');\n\t\t\t\tlet firstHalf = pulledHTML.slice(0, targetPoint);\n\t\t\t\tlet secondHalf = pulledHTML.slice(targetPoint);\n\t\t\t\tpulledHTML = firstHalf.concat(payloadScript).concat(secondHalf);\n\t\t\t\tfs.writeFile(path.join(rootDir, '/node_modules/@storybook/core/dist/public/index.html'), pulledHTML, (err) => {\n\t\t\t\t\tif (err) console.error(err);\n\t\t\t\t\telse {\n\t\t\t\t\t\tvscode.window.showInformationMessage('Successfully injected script');\n\t\t\t\t\t};\n\t\t\t\t});\n\t\t\t}\n\t\t});\n\n\t//declare an empty array (of strings) to push our scripts to during the next part\n\t\tconst scriptArray : Array = [];\n\t\t//define a path to the root working directory of the user\n\t\tconst rootDir = fileURLToPath(vscode.workspace.workspaceFolders[0].uri.toString(true));\n\t\t//now let's read SB's outputted index.html file, and parse out what we need\n\t\tfs.readFile(path.join(rootDir, '/node_modules/@storybook/core/dist/public/index.html'), (err, data) => {\n\t\t\tif (err) console.error(err);\n\t\t\telse {\n\t\t\t\t//if we've read the HTML file, take its contents and stringify it\n\t\t\t\tlet outputFile = data.toString();\n\t\t\t\t// this log shows what our eventual permutations would look like as we carve out the scripts\n\t\t\t\t// vscode.window.showWarningMessage(`what's in it: ${outputFile.slice(outputFile.indexOf('')+6, outputFile.indexOf(''))} \\n`)\n\t\t\t\t//split out the body section of the retrieved html file\n\t\t\t\toutputFile = outputFile.slice(outputFile.indexOf('')+6, outputFile.indexOf(''));\n\t\t\t\tvscode.window.showWarningMessage(`${outputFile} \\n`)\n\n\t\t\t\t//this loop will peel out all the scripts so long as there are any to rip out\n\t\t\t\twhile (outputFile.includes(`\" tags behind\n\t\t\t\t\tlet temp = outputFile.slice(outputFile.indexOf(``));\n\t\t\t\t\tscriptArray.push(temp);\n\t\t\t\t\toutputFile = outputFile.slice(outputFile.indexOf(`\">`)+10);\n\t\t\t\t}\n\t\t\t};\n\t\t});\n\n
\n
\t\n\t
\n\t\n\t\n\t\n
\n\n\tdisposable = vscode.commands.registerCommand('extension.getStories', () => {\n\t\tbuild a command that retrieves Storybook files on startup\n\t\tcan be executed later if Storybook server is spun up after the extension opens\n\t\t\n\t\talso register this command at startup to crawl the file path\n\t\t${vscode.commands.executeCommand('extension.getStories')}\n\t\tvscode.window.showInformationMessage('Aesop is reading from your Storybook.');\n\n\t\tdefine a path to SB webpack bundle outputs (in user workspace /node_modules/ folder)\n\t\tif (vscode.workspace.workspaceFolders[0] !== undefined){\n\t\t\tconst distGlob = new vscode.RelativePattern(vscode.workspace.workspaceFolders[0], \"**(remove)/node_modules/@storybook/core/dist/public\");\n\t\t\t//instantiate a watcher to listen for fs path changes (e.g. file creation/update)\n\t\t\t//bools = options for ignoreCreateEvents?, ignoreChangeEvents?, ignoreDeleteEvents?\t\n\t\t\tconst observer = vscode.workspace.createFileSystemWatcher(distGlob, false, false, false);\n\t\t\t// observer.onDidChange = //resolve//;\t\t// observer.onDidCreate = //resolve//;\n\t\t\t//extract index.html file that outputs into SB's preview pane\n\t\t\tconst htmlGlob = new vscode.RelativePattern(vscode.workspace.workspaceFolders[0], \"*(remove)/node_modules/@storybook/core/dist/public/*.html\");\n\t\t\t//extract necessary bundle scripts to leverage in-app dependencies\n\t\t\tconst scriptGlob = new vscode.RelativePattern(vscode.workspace.workspaceFolders[0], \"*(remove)/node_modules/@storybook/core/dist/public/*.js\");\n\n\t\t\tconsole.log(vscode.Uri.file(fileURLToPath(`/node_modules/@storybook/core/dist/public`)));\n\n\t\t\t//do we need to resolve the Storybook UI script from the /dll/ folder?\n\t\t\t//if extract methods above fail, determine logic to parse out HTML/.js scripts (index 0?);\n\t\t\t//retrieve files with findFiles/relativeFilePath\n\t\t\tconst arrayOfScripts = vscode.workspace.findFiles(distGlob, null, 100);\n\t\t\t//dev check: have we successfully pulled down script files?\n\t\t\t//if so, should we then store them locally, or is there no point?\n\t\t\tif (arrayOfScripts !== undefined){\n\t\t\t\tvscode.window.showInformationMessage(\"Hey, dog: \" + `${arrayOfScripts}`);\n\t\t\t}\n\n\t\t\tvscode.window.showInformationMessage(`\n\t\t\trootPath: ${vscode.workspace.workspaceFolders[0]},\n\t\t\tvscode.Uri: ${vscode.Uri},\n\t\t\tworkspace: ${vscode.workspace},\n\t\t\tdistGlob: ${distGlob.toString()},\n\t\t\thtmlGlob: ${htmlGlob.toString()},\n\t\t\tscriptGlob: ${scriptGlob.toString()}\n\t\t\t`);\n\t\t};\n\n\t\tvscode.window.showInformationMessage(`\n\t\t\trootPath: ${vscode.workspace.workspaceFolders[0].uri.toString()},\\n\n\t\t\tvscode URI parseTest: ${vscode.Uri.parse('file://'+ '/node_modules/@storybook/core/dist/public/index.html')},\\n\n\t\t\tvscode URI parsed w escape: ${vscode.Uri.parse('file://'+ '/node_modules/\\@storybook/core/dist/public/index.html')},\\n\n\t\t\tvscode URI file Test: ${vscode.Uri.file('node_modules/@storybook/core/dist/public/index.html')}\n\t\t\t`);\n\t\t\t\n\t\tconsole.log(`\n\t\trootPath: ${vscode.workspace.workspaceFolders[0]},\n\t\tvscode.Uri: ${vscode.Uri},\n\t\tworkspace: ${vscode.workspace},\n\t\tfileSys: ${vscode.Uri.file(path.join('/'))}`);\n });\n */","module.exports = require(\"child_process\");","module.exports = require(\"fs\");","module.exports = require(\"os\");","module.exports = require(\"path\");","module.exports = require(\"url\");","module.exports = require(\"vscode\");"],"sourceRoot":""} \ No newline at end of file diff --git a/package.json b/package.json index 763f62f..da603f1 100644 --- a/package.json +++ b/package.json @@ -19,7 +19,7 @@ "contributes": { "taskDefinitions": [ { - "type": "runStorybook" + "type": "runStorybook" } ], "commands": [ @@ -36,40 +36,40 @@ } ], "configuration": { - "type": "object", - "title": "Configuration", - "properties": { - "aesop.port": { - "type": "number", - "default": 8509, - "description": "Port number" - }, - "aesop.host": { - "type": "string", - "default": "localhost", - "description": "Host address" - }, - "aesop.storyRegex": { - "type": "string", - "default": "**/*.story.*", - "description": "A regular expression that picks up story files in your project" - }, - "aesop.storybookFilterRegex": { - "type": "string", - "default": ".", - "description": "A regular expression to filter stories appearing in the explorer view" - } - } - }, - "views": { - "explorer": [ - { - "id": "storybook", - "name": "Storybook", - "when": "is-running-aesop" - } - ] - } + "type": "object", + "title": "Configuration", + "properties": { + "aesop.port": { + "type": "number", + "default": 8509, + "description": "Port number" + }, + "aesop.host": { + "type": "string", + "default": "localhost", + "description": "Host address" + }, + "aesop.storyRegex": { + "type": "string", + "default": "**/*.story.*", + "description": "A regular expression that picks up story files in your project" + }, + "aesop.storybookFilterRegex": { + "type": "string", + "default": ".", + "description": "A regular expression to filter stories appearing in the explorer view" + } + } + }, + "views": { + "explorer": [ + { + "id": "storybook", + "name": "Storybook", + "when": "is-running-aesop" + } + ] + } }, "scripts": { "vscode:prepublish": "webpack --mode production", diff --git a/src/extension.ts b/src/extension.ts index 4a59499..412fe1e 100644 --- a/src/extension.ts +++ b/src/extension.ts @@ -3,20 +3,62 @@ import { fileURLToPath } from 'url'; import * as path from 'path'; import * as fs from 'fs'; import * as ps from 'ps-node'; +import * as child_process from 'child_process'; export function activate(context: vscode.ExtensionContext) { let PORT = 6006; const host = 'localhost'; - let dependencyFound = false; - let foundSb = false; - let checkedProcesses = false; - + + class AesopPanel implements vscode.WebviewPanel { + viewType + title: string = 'Aesop' + webview: vscode.Webview = new AesopWebview + options: {retainContextWhenHidden: true} + viewColumn: vscode.ViewColumn.Beside + active: boolean = true + visible: boolean = true + onDidChangeViewState + onDidDispose + reveal + } + + class AesopWebview implements vscode.Webview{ + asWebviewUri: any + onDidReceiveMessage: any + postMessage: any + cspSource: any + html: string = + ` + + + + + Aesop + + + - - - ` - }) + vscode.window.showInformationMessage(`Aesop has found your Storybook dependency. Just a moment...`); + + if (checkedProcesses === false){ + //check to see if a storybook node process is already running + ps.lookup({command: 'node', psargs: 'ux'}, (err, resultList) => { + if (err){ + vscode.window.showErrorMessage(`Failed looking for running Node processes. Error: ${err}`); + } else { + vscode.window.showInformationMessage(`Aesop is checking for a running Storybook...`); + + //if the process lookup was able to find running processes, iterate through to review them + resultList.forEach((process) => { + + // ---> OUTPUT LOGGER <--- // + fs.writeFile(path.join(rootDir, 'YOLO.txt'), `Attempted launch log:\n`, + (err) => {console.log(`Couldn't output process information to YOLO.txt: ${err}`)}); + + //check if any running processes are using the start-storybook script + if(process.arguments[0].includes('storybook')){ + + //stretch goal: check for multiple instances of storybook and reconcile + //if so, extract port number and use that value to populate the webview with that contents + const pFlagIndex = process.arguments.indexOf('-p'); + if (pFlagIndex !== -1){ + PORT = parseInt(process.arguments[pFlagIndex+1]); + } + + // ---> OUTPUT LOGGER <--- // + fs.appendFile(path.join(rootDir, 'YOLO.txt'), `This process matches for 'storybook':\n + PID: ${process.pid}, COMMAND:${process.command}, ARGUMENTS: ${process.arguments}\n + PORT has been assigned to: ${PORT}`, (err) => {console.log(err)}); + + foundSb = true; + + }//---> close if process.arguments[0] contains storybook + }) //---> close resultList.forEach() + + checkedProcesses = true; + + //if no processes match 'storybook', we will have to spin up the storybook server + if (checkedProcesses === true && foundSb === false){ + + //starts by extracting the existing storybook port script in the package.json + fs.readFile(path.join(rootDir, 'package.json'), (err, data) => { + if (err){ + vscode.window.showErrorMessage(`Aesop is attempting to read ${rootDir}. Is there a package.json file here?`); + } else { + //enter the package.JSON file and retrieve its contents as a string + let packageJSON = JSON.parse(data.toString()); + let storybookScript = packageJSON.scripts.storybook; + + // ---> OUTPUT LOGGER <--- // + fs.appendFile(path.join(rootDir, 'YOLO.txt'), `Here is the script for "storybook":\n + ${storybookScript}`, (err) => {console.log(err)}); + + //iterate through that text string and parse out important flags + //it is more helpful to split it into an array separated by whitespace to grab these + let retrievedScriptArray = storybookScript.split(' '); + for (let i = 0; i < retrievedScriptArray.length; i++){ + //add flags as we implement further functionality + if (retrievedScriptArray[i] === '-p'){ + PORT = parseInt(retrievedScriptArray[i+1]); + fs.appendFile(path.join(rootDir, 'YOLO.txt'), `Port from script":\n${parseInt(retrievedScriptArray[i+1])}\n + Port at this moment:\n${PORT}\n`, (err) => {console.log(err)}); + break; + } else if (i === retrievedScriptArray.length-1){ + fs.appendFile(path.join(rootDir, 'YOLO.txt'), `Script found, but no port flag detected.\n + Port when no port flag found:\n${PORT}\n`, (err) => {console.log(err)}); + //ADD LOGIC TO HANDLE WHEN NO SCRIPT FLAG IS GIVEN + } + } + //add --ci tag to existing package.json with an fs function? + //process.scripts.storybook = `${storybookScript} --ci` + + //execute Ola's logic to launch the child process, passing rootDir as an options arg + const runSb = child_process.spawn('npm', ['run', 'storybook']); + vscode.window.showInformationMessage("Done looking. Aesop will now run Storybook."); + + runSb.stdout.on('data', (data) => { + console.log(`stdout: ${data}`); + }) + + runSb.on('error', function(err) { + console.error(err); + process.exit(1); + }) + + //This will make sure the child process is terminated on process exit + runSb.on('close', (code) => { + console.log(`Child process exited with code ${code}`) + }) + } + }) + } //close spin up server + + const panel = vscode.window.createWebviewPanel( + 'aesop-sb', + 'Aesop', + vscode.ViewColumn.Beside, + { + enableScripts: true, + localResourceRoots: [vscode.Uri.file(context.extensionPath)] + } + ); + + panel.webview.html = + ` + + + + + Aesop + + +