├── .gitignore ├── .vscode ├── keybindings.json ├── launch.json ├── settings.json └── tasks.json ├── .vscodeignore ├── CONTRIBUTING.md ├── README.md ├── aesop-0.1.0.vsix ├── out ├── extension.js ├── extension.js.map ├── src │ ├── extension.js │ ├── extension.js.map │ └── test │ │ ├── runTest.js │ │ ├── runTest.js.map │ │ └── suite │ │ ├── extension.test.js │ │ ├── extension.test.js.map │ │ ├── index.js │ │ └── index.js.map ├── test.js ├── test.js.map └── test │ ├── runTest.js │ ├── runTest.js.map │ └── suite │ ├── extension.test.js │ ├── extension.test.js.map │ ├── index.js │ └── index.js.map ├── package-lock.json ├── package.json ├── resources └── Aesop128x128.png ├── samples ├── React_Sample │ ├── .babelrc │ ├── .eslintrc.js │ ├── .storybook │ │ └── config.js │ ├── client │ │ ├── components │ │ │ ├── CharacterCard.jsx │ │ │ ├── CharacterCard.stories.js │ │ │ ├── CreateCharacter.jsx │ │ │ ├── CreateCharacter.stories.js │ │ │ ├── Task.js │ │ │ ├── Task.stories.js │ │ │ ├── TaskList.js │ │ │ ├── TaskList.stories.js │ │ │ └── index.css │ │ └── data │ │ │ ├── films.json │ │ │ ├── planets.json │ │ │ └── species.json │ ├── package-lock.json │ └── package.json └── Vue_Sample │ ├── .storybook │ ├── config.js │ └── main.js │ ├── package-lock.json │ ├── package.json │ └── src │ ├── App.vue │ ├── components │ ├── EmployeeForm.js │ ├── EmployeeForm.stories.js │ ├── EmployeeForm.vue │ ├── EmployeeTable.js │ ├── EmployeeTable.stories.js │ ├── EmployeeTable.vue │ ├── HelloWorld.vue │ └── index.css │ └── main.js ├── src ├── extension.ts ├── processes │ ├── commands.ts │ └── process.service.ts ├── test │ ├── runTest.ts │ └── suite │ │ ├── extension.test.ts │ │ └── index.ts ├── utils │ ├── logger.ts │ └── sbChecks.ts └── webview │ └── create-webview.ts ├── tsconfig.json └── webpack.config.js /.gitignore: -------------------------------------------------------------------------------- 1 | .gitignore 2 | /node_modules 3 | 4 | #ignore dist folder 5 | /dist 6 | 7 | #ignore out 8 | /out 9 | 10 | #ignore react node modules 11 | /samples/React_Sample/ 12 | /samples/Vue_Sample/ -------------------------------------------------------------------------------- /.vscode/keybindings.json: -------------------------------------------------------------------------------- 1 | 2 | [{ 3 | "key": "ctrl+k a", 4 | "mac": "cmd+k a", 5 | "command": "extension.aesopAwaken" 6 | }] 7 | -------------------------------------------------------------------------------- /.vscode/launch.json: -------------------------------------------------------------------------------- 1 | // A launch configuration that compiles the extension and then opens it inside a new window 2 | // Use IntelliSense to learn about possible attributes. 3 | // Hover to view descriptions of existing attributes. 4 | // For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387 5 | { 6 | "version": "0.2.0", 7 | "configurations": [ 8 | { 9 | "name": "Run Extension", 10 | "type": "node", 11 | "request": "launch", 12 | "runtimeExecutable": "${execPath}", 13 | "args": [ 14 | "--extensionDevelopmentPath=${workspaceFolder}" 15 | ], 16 | "outFiles": [ 17 | "${workspaceFolder}/dist/**/*.js" 18 | ], 19 | "preLaunchTask": "${defaultBuildTask}" 20 | }, 21 | { 22 | "name": "Extension Tests", 23 | "type": "extensionHost", 24 | "request": "launch", 25 | "runtimeExecutable": "${execPath}", 26 | "args": [ 27 | "--extensionDevelopmentPath=${workspaceFolder}", 28 | "--extensionTestsPath=${workspaceFolder}/out/test/" 29 | ], 30 | "outFiles": [ 31 | "${workspaceFolder}/out/test/**/*.js" 32 | ], 33 | "preLaunchTask": "test-compile" 34 | } 35 | ] 36 | } 37 | -------------------------------------------------------------------------------- /.vscode/settings.json: -------------------------------------------------------------------------------- 1 | // Place your settings in this file to overwrite default and user settings. 2 | { 3 | "files.exclude": { 4 | "out": false // set this to true to hide the "out" folder with the compiled JS files 5 | }, 6 | "search.exclude": { 7 | "out": true // set this to false to include "out" folder in search results 8 | }, 9 | // Turn off tsc task auto detection since we have the necessary tasks as npm scripts 10 | "typescript.tsc.autoDetect": "off", 11 | "git.ignoreLimitWarning": true 12 | } -------------------------------------------------------------------------------- /.vscode/tasks.json: -------------------------------------------------------------------------------- 1 | // See https://go.microsoft.com/fwlink/?LinkId=733558 2 | // for the documentation about the tasks.json format 3 | { 4 | "version": "2.0.0", 5 | "tasks": [ 6 | { 7 | "type": "npm", 8 | "script": "webpack", 9 | "problemMatcher": "$tsc-watch", 10 | "isBackground": true, 11 | "presentation": { 12 | "reveal": "never" 13 | }, 14 | "group": { 15 | "kind": "build", 16 | "isDefault": true 17 | } 18 | } 19 | ] 20 | } 21 | -------------------------------------------------------------------------------- /.vscodeignore: -------------------------------------------------------------------------------- 1 | .vscode 2 | node_modules 3 | out/ 4 | src/ 5 | tsconfig.json 6 | webpack.config.js 7 | .gitignore 8 | vsc-extension-quickstart.md 9 | **/tsconfig.json 10 | **/tslint.json -------------------------------------------------------------------------------- /CONTRIBUTING.md: -------------------------------------------------------------------------------- 1 | # Contributing To Aesop for Storybook 2 | 3 | Thanks for your consideration on contributing to Aesop for Storybook! Each contribution helps make using Aesop for Storybook a better experience for everyone. 4 | 5 | Aesop for Storybook is an open source project and thrives on community contributions! These contributions can come in many forms-- anywhere from improving documentation to submitting bug reports and feature requests. 6 | 7 | We are also open to any code contributions that can be assimilated into the extension itself! For inspiration, take a look at our roadmap below. 8 | 9 | ## First Time Contributing? 10 | 11 | First time contributing to an open source project? You can learn more [here!](https://egghead.io/courses/how-to-contribute-to-an-open-source-project-on-github) 12 | 13 | Now, you’re ready to contribute. 14 | 15 | ## Getting Started 16 | 17 | If you find an area where you want to contribute, please fork the repository and create a branch with a descriptive name. 18 | 19 | A good branch name would be (where issue #234 is the ticket you're working on): 20 | `git checkout -b 234-add-treeview` 21 | 22 | Afterwards, if you feel like this contribution might help the project, feel free to send a pull request. 23 | 24 | ## Testing and Debugging Locally 25 | 26 | After forking and cloning the repository, open the folder in VS Code. Make sure that your root directory is the Aesop folder. Once there, you can launch the VS Code built-in debugger using the shortcut F5. You can learn more about this [here](https://code.visualstudio.com/docs/editor/debugging) 27 | 28 | After pressing F5, VS Code will build the extension and launch an Extension Development Host window as seen below. In order to test the extension, you will need to open a Storybook project as your root directory in VS Code, making sure that Storybook is a dependency in your node modules folder. 29 | 30 | ![extension development host](https://user-images.githubusercontent.com/55175891/73625080-60c2f800-4611-11ea-893c-c3128b561a28.PNG) 31 | 32 | Once you've gotten everything set up, you can launch Aesop's webview by selecting 'Aesop Awaken' from the command palette *(CTRL+SHIFT+P)* or using the shortcut *(CTRL K+A)*. 33 | 34 | You can also make use of VS Code's Webview Developer tools by selecting them in the command palette. 35 | 36 | ![dev tools webview](https://user-images.githubusercontent.com/55175891/73625433-ce235880-4612-11ea-9009-62141866e3d3.PNG) 37 | 38 | Closing the Extension Development Host will also close all Aesop child processes and Storybook instances run within it. 39 | 40 | However, be mindful. **The Extension Development Host will run the LAST WORKING VERSION of the extension. This means if you've introduced breaking changes, the version you're seeing might not be running the code you think.** To get around this, we usually implement a sort of hack-around solution by including a text counter as an HTML element within the web-view, changing it as we iterate. ...There's probably a better solution to this, but it's been working thus far. 41 | 42 | ## How to Report a Bug 43 | 44 | If you find a security vulnerability, please do NOT open an issue. Send a message to AesopStorybook@gmail.com instead. 45 | 46 | When filing an issue, make sure to answer these questions: 47 | 48 | 1. What version of VS Code are you using? 49 | 2. What version of Storybook are you using for your project? 50 | 3. What operating system and processor architecture are you using? 51 | 4. What did you do? Please also include the following details: 52 | a. Was Storybook currently running before you launched the extension command? 53 | b. Did you have a port flag defined in your package.json storybook script? 54 | 5. What did you expect to see? 55 | 6. What did you see instead? 56 | 57 | ## How to Suggest a Feature 58 | 59 | Aesop’s philosophy is to provide a seamless developer experience for using Storybook within VS Code. We want to keep the extension as light weight and easy to use as possible out of the box. 60 | 61 | If you think of any feature that you might like to see in Aesop for Storybook, please open an issue on our issues list on Github describing the feature you’d like to see, why you need it, and how it should work. 62 | 63 | ## Roadmap 64 | 65 | 1. Fine-tuning windows compatibility for all developer workflows 66 | a. Storybook is already running w/ port flag defined in npm run storybook script(*working*) 67 | b. Storybook is already running w/o port flag defined 68 | (*working*) 69 | c. Storybook is not currently running w/ port flag defined (*not working*) 70 | d. Storybook is not currently running w/o port flag defined (*not working*) 71 | 72 | 2. Add cross-platform testing. 73 | 74 | 3. Separate Storybook Manager from Preview iframe, replacing it with a vscode tree-view allowing you to interact with the Storybook preview from within the vscode explorer menu. 75 | 76 | ## Code Review Process 77 | 78 | Under Construction 79 | 80 | ## Community 81 | 82 | Under Construction 83 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | ![AesopLogo_small](https://user-images.githubusercontent.com/55175891/72542775-b433f880-3852-11ea-8483-02066bc9e8ca.jpg) 2 | 3 | # AESOP 4 | Meet Aesop: the lightweight Storybook preview extension. 5 | 6 | This humble helper displays your Storybook alongside a codebase for more responsive workflow. It integrates with existing Storybook addons and features, and it is optimized to use minimal system resources. 7 | 8 | ## Screenshots 9 | ![Aesop Awoken](https://user-images.githubusercontent.com/55175891/72540358-b3996300-384e-11ea-9477-e8823d1aedaa.gif) 10 | 11 | Here we activate the "Aesop Awaken" command from the command palette to jumpstart the initialization process that checks whether your storybook is currently running. In this case, we have already run a Storybook server from the command line, so Aesop dynamically selects the port where the content is being served and displays it in a webview. 12 | 13 | ## Features 14 | If you are working in a project folder on a Storybook-enabled application, Aesop will run a Storybook process at startup and display the same suite you're used to right inside Visual Studio Code as an attached Node child process. 15 | 16 | Or, if you're used to starting up your Storybook from the CLI with additional arguments, Aesop won't impede your workflow — it understands Node processes, and will happily retrieve your running Storybook. 17 | 18 | ## How To Use The Extension 19 | Simply install the extension from the Visual Studio Code Marketplace and open a project folder with a Storybook dependency as your main workspace folder. 20 | 21 | Then you can start previewing Storybook directly in your editor after following a few steps: 22 | 23 | First, execute the 'Aesop Awaken' command from the command palette, or by using the shortcut keybinding. 24 | 25 | From here, Aesop checks to see whether or not you currently have a Storybook process running. 26 | 27 | If it does not find a Storybook process, it will spin up a new instance of Storybook using your npm script within your package.json, along with any arguments you've supplied. 28 | 29 | If it does find a Storybook process, it dynamically captures the location in which the content is being served and displays it within a webview directly in your IDE. 30 | 31 | ## Requirements 32 | Aesop only depends on the ps-node library. This is used to simplify certain lookup functions while accessing running Node processes, but will likely be removed in a future version to make Aesop dependency-free. 33 | 34 | If your system does not support Netstat, you may experience some issues using this beta release. 35 | 36 | ## Extension Settings 37 | Because Aesop is lightweight, it is also minimal config. It contributes one hotkey command chord to activate: CTRL / CMD K + A 38 | 39 | The Aesop team aims to provide further customization options and improved UI integration within Visual Studio Code as development continues. 40 | 41 | ## Release Notes 42 | Please contact the developers at https://github.com/storybookjs/vs-code-plugin with comments, questions, and any features you would like to see in a future version of Aesop. 43 | 44 | ## Known Issues 45 | On Windows, you MUST have Storybook already running for Aesop to work. We are currently tackling this issue and expect it to be resolved soon. 46 | 47 | ### 0.1.0 48 | Aesop is pleased to make your acquaintance. 49 | 50 | If you are downloading the repository to play with Aesop's code, you may need to install dependencies for the sample React and Vue component files before use. Happy testing! 51 | -------------------------------------------------------------------------------- /aesop-0.1.0.vsix: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/storybookjs/vs-code-plugin/4e3eb00ad58c45b52fd5da4cb2e7e7e07c230dba/aesop-0.1.0.vsix -------------------------------------------------------------------------------- /out/extension.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | Object.defineProperty(exports, "__esModule", { value: true }); 3 | const vscode = require("vscode"); 4 | const url_1 = require("url"); 5 | const path = require("path"); 6 | const fs = require("fs"); 7 | const ps = require("ps-node"); 8 | const child_process = require("child_process"); 9 | const events = require("events"); 10 | const os = require("os"); 11 | function activate(context) { 12 | //define PORT and host variables to feed the webview content from SB server 13 | let PORT; 14 | let host = 'localhost'; //arl 15 | const aesopEmitter = new events.EventEmitter(); 16 | let emittedAesop = false; 17 | const platform = os.platform(); 18 | const commands = { 19 | linux: { 20 | cmd: 'netstat', 21 | args: ['-apntu'], 22 | }, 23 | darwin: { 24 | cmd: 'netstat', 25 | args: ['-v', '-n', '-p', 'tcp'], 26 | }, 27 | win32: { 28 | cmd: 'netstat.exe', 29 | args: ['-a', '-n', '-o'], 30 | }, 31 | }; 32 | const command = commands[platform]; 33 | let instances = 0; 34 | //@TODO: if aesop already opened sb in webview - subsequent calls to aesop should not open a new webview 35 | //set context "aesop-awake" to true; enabling views 36 | vscode.commands.executeCommand("setContext", "aesop-awake", true); 37 | //create the status bar to let the user know what Aesop is doing 38 | const statusText = vscode.window.createStatusBarItem(vscode.StatusBarAlignment.Left, 7); 39 | statusText.text = "Aesop is finding your Storybook dependency..."; 40 | statusText.color = "#FFFFFF"; 41 | statusText.command = undefined; 42 | statusText.tooltip = "Aesop status"; 43 | //create disposable to register Aesop Awaken command to subscriptions 44 | let disposable = vscode.commands.registerCommand('extension.aesopAwaken', () => { 45 | statusText.show(); 46 | //declare variable to toggle whether a running SB process was found 47 | let foundSb = false; 48 | //define a path to the user's root working directory 49 | const rootDir = url_1.fileURLToPath(vscode.workspace.workspaceFolders[0].uri.toString(true)); 50 | //first test whether Storybook has been depended into your application 51 | fs.access(path.join(rootDir, '/node_modules/@storybook'), (err) => { 52 | //if the filepath isn't found, show the user what Aesop is reading as the root path 53 | if (err) { 54 | vscode.window.showErrorMessage(`Aesop could not find Storybook as a dependency in the active folder, ${rootDir}`); 55 | throw new Error('Error finding a storybook project'); 56 | } 57 | else { 58 | statusText.text = "Aesop found a Storybook project."; 59 | //check to see if a storybook node process is already running 60 | ps.lookup({ 61 | command: 'node', 62 | psargs: 'ux' 63 | }, (err, resultList) => { 64 | if (err) { 65 | vscode.window.showErrorMessage(`Failed looking for running Node processes. Error: ${err}`); 66 | statusText.dispose(); 67 | throw new Error('Failed looking for running Node processes.'); 68 | } 69 | else { 70 | //notify the user that Aesop is checking for a running Storybook instances 71 | statusText.text = `Reviewing Node processes...`; 72 | //if the process lookup was able to find running processes, iterate through to review them 73 | resultList.forEach((process) => { 74 | //check if any running processes are Storybook processes 75 | //stretch feature: check for multiple instances of storybook and reconcile 76 | if (process.arguments[0].includes('node_modules') && process.arguments[0].includes('storybook')) { 77 | //if so, extract port number and use that value to populate the webview with that contents 78 | const pFlagIndex = process.arguments.indexOf('-p'); 79 | //also grab the process id to use netstat in the else condition 80 | const processPid = parseInt(process['pid']).toString(); 81 | //if a port flag has been defined in the process args, retrieve the user's config 82 | if (pFlagIndex !== -1) { 83 | PORT = parseInt(process.arguments[pFlagIndex + 1]); 84 | aesopEmitter.emit('sb_on'); 85 | return; 86 | } 87 | else { 88 | //if no port flag defined, dynamically retrieve port with netstat 89 | const netStatProcess = child_process.spawn(command.cmd, command.args); 90 | const grepProcess = child_process.spawn('grep', [processPid]); 91 | netStatProcess.stdout.pipe(grepProcess.stdin); 92 | grepProcess.stdout.setEncoding('utf8'); 93 | grepProcess.stdout.on('data', (data) => { 94 | const parts = data.split(/\s/).filter(String); 95 | //@TODO: refactor for platform specific or grab port dynamically 96 | const partIndex = (platform === 'win32') ? 1 : 3; 97 | console.log(parts); 98 | PORT = parseInt(parts[partIndex].replace(/[^0-9]/g, '')); 99 | aesopEmitter.emit('sb_on'); 100 | process.send('killNet'); 101 | process.send('killGrep'); 102 | return; 103 | }); 104 | process.on('killGrep', () => { 105 | console.log(`Killed Grep`); 106 | grepProcess.kill(); 107 | }); 108 | netStatProcess.on('killNet', () => { 109 | console.log(`Killed Net`); 110 | netStatProcess.kill(); 111 | }); 112 | netStatProcess.stdout.on('exit', (code) => { 113 | vscode.window.showInformationMessage(`Netstat ended with ${code}`); 114 | }); 115 | grepProcess.stdout.on('exit', (code) => { 116 | vscode.window.showInformationMessage(`Grep ended with ${code}`); 117 | }); 118 | } 119 | //set foundSb to true to prevent our function from running another process 120 | foundSb = true; 121 | //once port is known, fire event emitter to instantiate webview 122 | statusText.text = `Retrieving running Storybook process...`; 123 | } //---> close if process.arguments[0] contains storybook 124 | }); //---> close resultList.forEach() 125 | //having checked running Node processes, set that variable to true 126 | //if no processes matched 'storybook', we will have to spin up the storybook server 127 | if (foundSb === false) { 128 | //starts by checking for/extracting any port flags from the SB script in the package.json 129 | fs.readFile(path.join(rootDir, 'package.json'), (err, data) => { 130 | if (err) { 131 | vscode.window.showErrorMessage(`Aesop is attempting to read ${rootDir}. Is there a package.json file here?`); 132 | statusText.dispose(); 133 | } 134 | else { 135 | statusText.text = `Checking package.json...`; 136 | //enter the package.JSON file and retrieve its contents as an object 137 | let packageJSON = JSON.parse(data.toString()); 138 | let storybookScript = packageJSON.scripts.storybook; 139 | //iterate through the text string (stored on "storybook" key) and parse out port flag 140 | //it is more helpful to split it into an array separated by whitespace to grab this 141 | let retrievedScriptArray = storybookScript.split(' '); 142 | //@TODO if script already includes --ci, no need to add it 143 | //older Windows systems support here: check platform, change process command accordingly 144 | let platform = os.platform(); 145 | const sbCLI = './node_modules/.bin/start-storybook'; 146 | const sbStartIndex = retrievedScriptArray.indexOf('start-storybook'); 147 | retrievedScriptArray[sbStartIndex] = sbCLI; 148 | retrievedScriptArray.push('--ci'); 149 | //now launch the child process on the port you've derived 150 | const childProcessArguments = (platform === 'win32') ? ['run', 'storybook'] : retrievedScriptArray; 151 | const childProcessCommand = (platform === 'win32') ? 'npm.cmd' : 'node'; 152 | const runSb = child_process.spawn(childProcessCommand, childProcessArguments, { cwd: rootDir, detached: true, env: process.env, windowsHide: false, windowsVerbatimArguments: true }); 153 | // if (platform === 'win32') { 154 | // let runSb = child_process.spawn('npm.cmd', ['run', 'storybook'], {cwd: rootDir, detached: true, env: process.env, windowsHide: false, windowsVerbatimArguments: true }); 155 | // } else { 156 | // let runSb = child_process.spawn('node', retrievedScriptArray, {cwd: rootDir, detached: false, env: process.env }); 157 | // } 158 | statusText.text = `Done looking. Aesop will now launch Storybook in the background.`; 159 | runSb.stdout.setEncoding('utf8'); 160 | let counter = 0; 161 | //Storybook outputs three messages to the terminal as it spins up 162 | //grab the port from the last message to listen in on the process 163 | runSb.stdout.on('data', (data) => { 164 | if (emittedAesop === true) 165 | return; 166 | let str = data.toString().split(" "); 167 | counter += 1; 168 | if (counter >= 2) { 169 | for (let i = 165; i < str.length; i += 1) { 170 | if (str[i].includes('localhost')) { 171 | const path = str[i]; 172 | const regExp = (/[^0-9]/g); 173 | PORT = (path.replace(regExp, "")); 174 | emittedAesop = true; 175 | aesopEmitter.emit('sb_on'); 176 | return; 177 | } 178 | } 179 | } 180 | }); 181 | runSb.on('error', (err) => { 182 | console.log(err); 183 | process.exit(1); 184 | }); 185 | //make sure the child process is terminated on process exit 186 | runSb.on('exit', (code) => { 187 | console.log(`child process exited with code ${code}`); 188 | }); 189 | } 190 | }); 191 | } //close spin up server 192 | } 193 | ; //CLOSE else psLookup 194 | }); //close ps LOOKUP //close depend found, not checked processes 195 | } //close else statement in fs.access 196 | }); //close fs access 197 | aesopEmitter.on('sb_on', () => { 198 | createAesopOnce(PORT, host); 199 | }); 200 | const createAesopOnce = once(createAesop); 201 | function once(func) { 202 | return function addedOnce(...args) { 203 | if (instances < 1) { 204 | instances += 1; 205 | const panel = func(...args); 206 | panel.onDidDispose(() => { 207 | vscode.window.showInformationMessage(`We got a disposed`); 208 | instances = 0; 209 | }, null, context.subscriptions); 210 | return; 211 | } 212 | vscode.window.showInformationMessage(`Aesop has already been run`); 213 | throw new Error(); 214 | }; 215 | } 216 | function createAesop(PORT, host) { 217 | statusText.hide(); 218 | vscode.window.showInformationMessage(`Welcome to Aesop Storybook`); 219 | const panel = vscode.window.createWebviewPanel('aesop-sb', 'Aesop', vscode.ViewColumn.Beside, { 220 | enableCommandUris: true, 221 | enableScripts: true, 222 | portMapping: [{ 223 | webviewPort: PORT, 224 | extensionHostPort: PORT 225 | }], 226 | localResourceRoots: [vscode.Uri.file(context.extensionPath)], 227 | }); 228 | panel.webview.html = ` 229 | 230 | 231 | 232 | 233 | 234 | Aesop 235 | 239 | 240 | 241 | 242 | 243 | `; 244 | // panel.onDidDispose(() => { 245 | // vscode.window.showInformationMessage(`We got a disposed`); 246 | // }, 247 | // null, 248 | // context.subscriptions) 249 | return panel; 250 | } // close createAesop helper function 251 | }); //close disposable 252 | context.subscriptions.push(disposable); 253 | } 254 | exports.activate = activate; 255 | function deactivate() { 256 | process.exit(); 257 | } 258 | exports.deactivate = deactivate; 259 | //# sourceMappingURL=extension.js.map -------------------------------------------------------------------------------- /out/extension.js.map: -------------------------------------------------------------------------------- 1 | {"version":3,"file":"extension.js","sourceRoot":"","sources":["../src/extension.ts"],"names":[],"mappings":"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"} -------------------------------------------------------------------------------- /out/src/extension.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | Object.defineProperty(exports, "__esModule", { value: true }); 3 | const vscode = require("vscode"); 4 | const express = require("express"); 5 | //port should be variable to listen for action in the user's active terminal 6 | const PORT = 6006; 7 | const server = express(); 8 | function activate(context) { 9 | server.get('/', (req, res) => { 10 | vscode.window.showInformationMessage('Aesop server online'); 11 | res.end(); 12 | }); 13 | server.listen(PORT); 14 | //create disposable variable type, registers awaken command & opens webview 15 | let disposable = vscode.commands.registerCommand('extension.aesopAwaken', () => { 16 | const panel = vscode.window.createWebviewPanel('aesop-sb', 'Aesop', vscode.ViewColumn.Beside, { 17 | enableScripts: true, 18 | portMapping: [ 19 | //should extensionHostPort be variable to enable remote machine access? 20 | //PORT is presently undefined 21 | //how to use express with a d.ts file 22 | { webviewPort: PORT, extensionHostPort: PORT } 23 | ], 24 | // (!) look in to workspace file system access 25 | localResourceRoots: [vscode.Uri.file(context.extensionPath)] 26 | }); 27 | //{ 28 | //also register this command at startup to crawl the file path 29 | // ${vscode.commands.executeCommand('extension.getStories')} 30 | // vscode.window.showInformationMessage('Aesop is reading from your Storybook.'); 31 | // 32 | //access the first opened folder of the workspace array 33 | //a potentially problematic assumption in multi-folder workspaces 34 | const rootPath = vscode.workspace.workspaceFolders[0]; 35 | //define a path to SB webpack bundle outputs (in user workspace /node_modules/ folder) 36 | const distGlob = new vscode.RelativePattern(rootPath, "*/node_modules/@storybook/core/dist/public/"); 37 | //instantiate a watcher to listen for fs path changes (e.g. file creation/update) 38 | //bools = options for ignoreCreateEvents?, ignoreChangeEvents?, ignoreDeleteEvents? 39 | const observer = vscode.workspace.createFileSystemWatcher(distGlob, false, false, true); 40 | // observer.onDidChange = /*resolve*/; 41 | // observer.onDidCreate = /*resolve*/; 42 | //extract the index.html file that outputs into SB's preview pane 43 | const htmlGlob = new vscode.RelativePattern(rootPath, "*/node_modules/@storybook/core/dist/public/*.html"); 44 | //extract the necessary bundle scripts to leverage in-app dependencies 45 | const scriptGlob = new vscode.RelativePattern(rootPath, "*/node_modules/@storybook/core/dist/public/*.js"); 46 | //do we need to resolve the Storybook UI script from the /dll/ folder? 47 | //if extract methods above fail, determine logic to parse out HTML/.js scripts (index 0?); 48 | //retrieve files with findFiles/relativeFilePath 49 | const arrayOfScripts = vscode.workspace.findFiles(distGlob, null, 100); 50 | //dev check: have we successfully pulled down script files? 51 | //if so, should we then store them locally, or is there no point? 52 | if (arrayOfScripts !== undefined) { 53 | vscode.window.showInformationMessage("Hey, dog: " + arrayOfScripts); 54 | } 55 | //use retrieved info to fill out our HTML template inside the webview 56 | //figure out how to use a tsx rule in webpack 57 | //signal to babel to interpret this block as tsx, e.g. 58 | //something like: @ tsx babel// (to determine syntax) 59 | //a toggle for the background -> black if no stories to show 60 | const backgroundColor = (rootPath === undefined) ? "black" : "white"; 61 | panel.webview.html = 62 | ` 63 | 64 | 65 | 66 | 67 | Aesop 68 | 73 | 74 | 75 | 78 | 79 | 80 | 81 | `; 82 | // vscode.window.showInformationMessage(`Aesop is ready to chronicle your stories!\n\nPlease use a command to begin: ${vscode.commands.getCommands(true)}`); 83 | }); 84 | //subscribe this extension to the disposable 85 | context.subscriptions.push(disposable); 86 | //break up subscription pushes, and register each command sequentially. 87 | //this lets us overwrite "disposable," avoiding creation of unnecessary variables 88 | disposable = vscode.commands.registerCommand('extension.tollTheHour', () => { 89 | const nowadays = new Date(Date.now()).toTimeString(); 90 | vscode.window.showInformationMessage(`The hour tolls: ${nowadays}`); 91 | }); 92 | context.subscriptions.push(disposable); 93 | disposable = vscode.commands.registerCommand('extension.getStories', () => { 94 | //build a command that retrieves Storybook files on startup 95 | //can be executed later if Storybook server is spun up after the extension opens 96 | vscode.window.showInformationMessage(`Aesop has read the script in your webview HTML!`); 97 | }); 98 | context.subscriptions.push(disposable); 99 | } 100 | exports.activate = activate; 101 | function deactivate() { 102 | } 103 | exports.deactivate = deactivate; 104 | //# sourceMappingURL=extension.js.map -------------------------------------------------------------------------------- /out/src/extension.js.map: -------------------------------------------------------------------------------- 1 | {"version":3,"file":"extension.js","sourceRoot":"","sources":["../../src/extension.ts"],"names":[],"mappings":"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"} -------------------------------------------------------------------------------- /out/src/test/runTest.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { 3 | function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); } 4 | return new (P || (P = Promise))(function (resolve, reject) { 5 | function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } 6 | function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } 7 | function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); } 8 | step((generator = generator.apply(thisArg, _arguments || [])).next()); 9 | }); 10 | }; 11 | Object.defineProperty(exports, "__esModule", { value: true }); 12 | const path = require("path"); 13 | const vscode_test_1 = require("vscode-test"); 14 | function main() { 15 | return __awaiter(this, void 0, void 0, function* () { 16 | try { 17 | // The folder containing the Extension Manifest package.json 18 | // Passed to `--extensionDevelopmentPath` 19 | const extensionDevelopmentPath = path.resolve(__dirname, '../../'); 20 | // The path to test runner 21 | // Passed to --extensionTestsPath 22 | const extensionTestsPath = path.resolve(__dirname, './suite/index'); 23 | // Download VS Code, unzip it and run the integration test 24 | yield vscode_test_1.runTests({ extensionDevelopmentPath, extensionTestsPath }); 25 | } 26 | catch (err) { 27 | console.error('Failed to run tests'); 28 | process.exit(1); 29 | } 30 | }); 31 | } 32 | main(); 33 | //# sourceMappingURL=runTest.js.map -------------------------------------------------------------------------------- /out/src/test/runTest.js.map: -------------------------------------------------------------------------------- 1 | {"version":3,"file":"runTest.js","sourceRoot":"","sources":["../../../src/test/runTest.ts"],"names":[],"mappings":";;;;;;;;;;;AAAA,6BAA6B;AAE7B,6CAAuC;AAEvC,SAAe,IAAI;;QAClB,IAAI;YACH,4DAA4D;YAC5D,yCAAyC;YACzC,MAAM,wBAAwB,GAAG,IAAI,CAAC,OAAO,CAAC,SAAS,EAAE,QAAQ,CAAC,CAAC;YAEnE,0BAA0B;YAC1B,iCAAiC;YACjC,MAAM,kBAAkB,GAAG,IAAI,CAAC,OAAO,CAAC,SAAS,EAAE,eAAe,CAAC,CAAC;YAEpE,0DAA0D;YAC1D,MAAM,sBAAQ,CAAC,EAAE,wBAAwB,EAAE,kBAAkB,EAAE,CAAC,CAAC;SACjE;QAAC,OAAO,GAAG,EAAE;YACb,OAAO,CAAC,KAAK,CAAC,qBAAqB,CAAC,CAAC;YACrC,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;SAChB;IACF,CAAC;CAAA;AAED,IAAI,EAAE,CAAC"} -------------------------------------------------------------------------------- /out/src/test/suite/extension.test.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | Object.defineProperty(exports, "__esModule", { value: true }); 3 | const assert = require("assert"); 4 | // You can import and use all API from the 'vscode' module 5 | // as well as import your extension to test it 6 | const vscode = require("vscode"); 7 | // import * as myExtension from '../extension'; 8 | suite('Extension Test Suite', () => { 9 | vscode.window.showInformationMessage('Start all tests.'); 10 | test('Sample test', () => { 11 | assert.equal(-1, [1, 2, 3].indexOf(5)); 12 | assert.equal(-1, [1, 2, 3].indexOf(0)); 13 | }); 14 | }); 15 | //# sourceMappingURL=extension.test.js.map -------------------------------------------------------------------------------- /out/src/test/suite/extension.test.js.map: -------------------------------------------------------------------------------- 1 | {"version":3,"file":"extension.test.js","sourceRoot":"","sources":["../../../../src/test/suite/extension.test.ts"],"names":[],"mappings":";;AAAA,iCAAiC;AAEjC,0DAA0D;AAC1D,8CAA8C;AAC9C,iCAAiC;AACjC,+CAA+C;AAE/C,KAAK,CAAC,sBAAsB,EAAE,GAAG,EAAE;IAClC,MAAM,CAAC,MAAM,CAAC,sBAAsB,CAAC,kBAAkB,CAAC,CAAC;IAEzD,IAAI,CAAC,aAAa,EAAE,GAAG,EAAE;QACxB,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,CAAC;QACvC,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,CAAC;IACxC,CAAC,CAAC,CAAC;AACJ,CAAC,CAAC,CAAC"} -------------------------------------------------------------------------------- /out/src/test/suite/index.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | Object.defineProperty(exports, "__esModule", { value: true }); 3 | const path = require("path"); 4 | const Mocha = require("mocha"); 5 | const glob = require("glob"); 6 | function run() { 7 | // Create the mocha test 8 | const mocha = new Mocha({ 9 | ui: 'tdd', 10 | }); 11 | mocha.useColors(true); 12 | const testsRoot = path.resolve(__dirname, '..'); 13 | return new Promise((c, e) => { 14 | glob('**/**.test.js', { cwd: testsRoot }, (err, files) => { 15 | if (err) { 16 | return e(err); 17 | } 18 | // Add files to the test suite 19 | files.forEach(f => mocha.addFile(path.resolve(testsRoot, f))); 20 | try { 21 | // Run the mocha test 22 | mocha.run(failures => { 23 | if (failures > 0) { 24 | e(new Error(`${failures} tests failed.`)); 25 | } 26 | else { 27 | c(); 28 | } 29 | }); 30 | } 31 | catch (err) { 32 | e(err); 33 | } 34 | }); 35 | }); 36 | } 37 | exports.run = run; 38 | //# sourceMappingURL=index.js.map -------------------------------------------------------------------------------- /out/src/test/suite/index.js.map: -------------------------------------------------------------------------------- 1 | {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../../src/test/suite/index.ts"],"names":[],"mappings":";;AAAA,6BAA6B;AAC7B,+BAA+B;AAC/B,6BAA6B;AAE7B,SAAgB,GAAG;IAClB,wBAAwB;IACxB,MAAM,KAAK,GAAG,IAAI,KAAK,CAAC;QACvB,EAAE,EAAE,KAAK;KACT,CAAC,CAAC;IACH,KAAK,CAAC,SAAS,CAAC,IAAI,CAAC,CAAC;IAEtB,MAAM,SAAS,GAAG,IAAI,CAAC,OAAO,CAAC,SAAS,EAAE,IAAI,CAAC,CAAC;IAEhD,OAAO,IAAI,OAAO,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE;QAC3B,IAAI,CAAC,eAAe,EAAE,EAAE,GAAG,EAAE,SAAS,EAAE,EAAE,CAAC,GAAG,EAAE,KAAK,EAAE,EAAE;YACxD,IAAI,GAAG,EAAE;gBACR,OAAO,CAAC,CAAC,GAAG,CAAC,CAAC;aACd;YAED,8BAA8B;YAC9B,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,EAAE,CAAC,KAAK,CAAC,OAAO,CAAC,IAAI,CAAC,OAAO,CAAC,SAAS,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC;YAE9D,IAAI;gBACH,qBAAqB;gBACrB,KAAK,CAAC,GAAG,CAAC,QAAQ,CAAC,EAAE;oBACpB,IAAI,QAAQ,GAAG,CAAC,EAAE;wBACjB,CAAC,CAAC,IAAI,KAAK,CAAC,GAAG,QAAQ,gBAAgB,CAAC,CAAC,CAAC;qBAC1C;yBAAM;wBACN,CAAC,EAAE,CAAC;qBACJ;gBACF,CAAC,CAAC,CAAC;aACH;YAAC,OAAO,GAAG,EAAE;gBACb,CAAC,CAAC,GAAG,CAAC,CAAC;aACP;QACF,CAAC,CAAC,CAAC;IACJ,CAAC,CAAC,CAAC;AACJ,CAAC;AAhCD,kBAgCC"} -------------------------------------------------------------------------------- /out/test.js: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/storybookjs/vs-code-plugin/4e3eb00ad58c45b52fd5da4cb2e7e7e07c230dba/out/test.js -------------------------------------------------------------------------------- /out/test.js.map: -------------------------------------------------------------------------------- 1 | {"version":3,"file":"test.js","sourceRoot":"","sources":["../test.ts"],"names":[],"mappings":"AAAA,SAAS,aAAa,CAAC,CAAC;IACpB,OAAO,CAAC,GAAC,CAAC,CAAA;AACd,CAAC;AAAA,CAAC;AAEF,aAAa,CAAC,KAAK,CAAC,CAAC;AAGrB,MAAM,GAAG,GAAG,CAAC,CAAC;AAEd,KAAI,IAAI,CAAC,GAAE,CAAC,EAAE,CAAC,GAAG,KAAK,EAAE,CAAC,EAAE,EAAC;CAE5B"} -------------------------------------------------------------------------------- /out/test/runTest.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { 3 | function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); } 4 | return new (P || (P = Promise))(function (resolve, reject) { 5 | function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } 6 | function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } 7 | function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); } 8 | step((generator = generator.apply(thisArg, _arguments || [])).next()); 9 | }); 10 | }; 11 | Object.defineProperty(exports, "__esModule", { value: true }); 12 | const path = require("path"); 13 | const vscode_test_1 = require("vscode-test"); 14 | function main() { 15 | return __awaiter(this, void 0, void 0, function* () { 16 | try { 17 | // The folder containing the Extension Manifest package.json 18 | // Passed to `--extensionDevelopmentPath` 19 | const extensionDevelopmentPath = path.resolve(__dirname, '../../'); 20 | // The path to test runner 21 | // Passed to --extensionTestsPath 22 | const extensionTestsPath = path.resolve(__dirname, './suite/index'); 23 | // Download VS Code, unzip it and run the integration test 24 | yield vscode_test_1.runTests({ extensionDevelopmentPath, extensionTestsPath }); 25 | } 26 | catch (err) { 27 | console.error('Failed to run tests'); 28 | process.exit(1); 29 | } 30 | }); 31 | } 32 | main(); 33 | //# sourceMappingURL=runTest.js.map -------------------------------------------------------------------------------- /out/test/runTest.js.map: -------------------------------------------------------------------------------- 1 | {"version":3,"file":"runTest.js","sourceRoot":"","sources":["../../src/test/runTest.ts"],"names":[],"mappings":";;;;;;;;;;;AAAA,6BAA6B;AAE7B,6CAAuC;AAEvC,SAAe,IAAI;;QAClB,IAAI;YACH,4DAA4D;YAC5D,yCAAyC;YACzC,MAAM,wBAAwB,GAAG,IAAI,CAAC,OAAO,CAAC,SAAS,EAAE,QAAQ,CAAC,CAAC;YAEnE,0BAA0B;YAC1B,iCAAiC;YACjC,MAAM,kBAAkB,GAAG,IAAI,CAAC,OAAO,CAAC,SAAS,EAAE,eAAe,CAAC,CAAC;YAEpE,0DAA0D;YAC1D,MAAM,sBAAQ,CAAC,EAAE,wBAAwB,EAAE,kBAAkB,EAAE,CAAC,CAAC;SACjE;QAAC,OAAO,GAAG,EAAE;YACb,OAAO,CAAC,KAAK,CAAC,qBAAqB,CAAC,CAAC;YACrC,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;SAChB;IACF,CAAC;CAAA;AAED,IAAI,EAAE,CAAC"} -------------------------------------------------------------------------------- /out/test/suite/extension.test.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | Object.defineProperty(exports, "__esModule", { value: true }); 3 | const assert = require("assert"); 4 | // You can import and use all API from the 'vscode' module 5 | // as well as import your extension to test it 6 | const vscode = require("vscode"); 7 | // import * as myExtension from '../extension'; 8 | suite('Extension Test Suite', () => { 9 | vscode.window.showInformationMessage('Start all tests.'); 10 | test('Sample test', () => { 11 | assert.equal(-1, [1, 2, 3].indexOf(5)); 12 | assert.equal(-1, [1, 2, 3].indexOf(0)); 13 | }); 14 | }); 15 | //# sourceMappingURL=extension.test.js.map -------------------------------------------------------------------------------- /out/test/suite/extension.test.js.map: -------------------------------------------------------------------------------- 1 | {"version":3,"file":"extension.test.js","sourceRoot":"","sources":["../../../src/test/suite/extension.test.ts"],"names":[],"mappings":";;AAAA,iCAAiC;AAEjC,0DAA0D;AAC1D,8CAA8C;AAC9C,iCAAiC;AACjC,+CAA+C;AAE/C,KAAK,CAAC,sBAAsB,EAAE,GAAG,EAAE;IAClC,MAAM,CAAC,MAAM,CAAC,sBAAsB,CAAC,kBAAkB,CAAC,CAAC;IAEzD,IAAI,CAAC,aAAa,EAAE,GAAG,EAAE;QACxB,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,CAAC;QACvC,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,CAAC;IACxC,CAAC,CAAC,CAAC;AACJ,CAAC,CAAC,CAAC"} -------------------------------------------------------------------------------- /out/test/suite/index.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | Object.defineProperty(exports, "__esModule", { value: true }); 3 | const path = require("path"); 4 | const Mocha = require("mocha"); 5 | const glob = require("glob"); 6 | function run() { 7 | // Create the mocha test 8 | const mocha = new Mocha({ 9 | ui: 'tdd', 10 | }); 11 | mocha.useColors(true); 12 | const testsRoot = path.resolve(__dirname, '..'); 13 | return new Promise((c, e) => { 14 | glob('**/**.test.js', { cwd: testsRoot }, (err, files) => { 15 | if (err) { 16 | return e(err); 17 | } 18 | // Add files to the test suite 19 | files.forEach(f => mocha.addFile(path.resolve(testsRoot, f))); 20 | try { 21 | // Run the mocha test 22 | mocha.run(failures => { 23 | if (failures > 0) { 24 | e(new Error(`${failures} tests failed.`)); 25 | } 26 | else { 27 | c(); 28 | } 29 | }); 30 | } 31 | catch (err) { 32 | e(err); 33 | } 34 | }); 35 | }); 36 | } 37 | exports.run = run; 38 | //# sourceMappingURL=index.js.map -------------------------------------------------------------------------------- /out/test/suite/index.js.map: -------------------------------------------------------------------------------- 1 | {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/test/suite/index.ts"],"names":[],"mappings":";;AAAA,6BAA6B;AAC7B,+BAA+B;AAC/B,6BAA6B;AAE7B,SAAgB,GAAG;IAClB,wBAAwB;IACxB,MAAM,KAAK,GAAG,IAAI,KAAK,CAAC;QACvB,EAAE,EAAE,KAAK;KACT,CAAC,CAAC;IACH,KAAK,CAAC,SAAS,CAAC,IAAI,CAAC,CAAC;IAEtB,MAAM,SAAS,GAAG,IAAI,CAAC,OAAO,CAAC,SAAS,EAAE,IAAI,CAAC,CAAC;IAEhD,OAAO,IAAI,OAAO,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE;QAC3B,IAAI,CAAC,eAAe,EAAE,EAAE,GAAG,EAAE,SAAS,EAAE,EAAE,CAAC,GAAG,EAAE,KAAK,EAAE,EAAE;YACxD,IAAI,GAAG,EAAE;gBACR,OAAO,CAAC,CAAC,GAAG,CAAC,CAAC;aACd;YAED,8BAA8B;YAC9B,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,EAAE,CAAC,KAAK,CAAC,OAAO,CAAC,IAAI,CAAC,OAAO,CAAC,SAAS,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC;YAE9D,IAAI;gBACH,qBAAqB;gBACrB,KAAK,CAAC,GAAG,CAAC,QAAQ,CAAC,EAAE;oBACpB,IAAI,QAAQ,GAAG,CAAC,EAAE;wBACjB,CAAC,CAAC,IAAI,KAAK,CAAC,GAAG,QAAQ,gBAAgB,CAAC,CAAC,CAAC;qBAC1C;yBAAM;wBACN,CAAC,EAAE,CAAC;qBACJ;gBACF,CAAC,CAAC,CAAC;aACH;YAAC,OAAO,GAAG,EAAE;gBACb,CAAC,CAAC,GAAG,CAAC,CAAC;aACP;QACF,CAAC,CAAC,CAAC;IACJ,CAAC,CAAC,CAAC;AACJ,CAAC;AAhCD,kBAgCC"} -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "aesop", 3 | "displayName": "Aesop", 4 | "description": "An IDE-native suite for previewing Storybook.", 5 | "version": "0.1.0", 6 | "publisher": "async-aesop", 7 | "repository": "https://github.com/storybookjs/vs-code-plugin", 8 | "icon": "resources/Aesop128x128.png", 9 | "engines": { 10 | "vscode": "^1.41.0" 11 | }, 12 | "categories": [ 13 | "Other" 14 | ], 15 | "activationEvents": [ 16 | "onCommand:extension.aesopAwaken", 17 | "workspaceContains:**/node_modules/@storybook/core/*.json" 18 | ], 19 | "main": "./dist/extension", 20 | "contributes": { 21 | "commands": [ 22 | { 23 | "command": "extension.aesopAwaken", 24 | "title": "Aesop Awaken" 25 | } 26 | ], 27 | "configuration": { 28 | "type": "object", 29 | "title": "Configuration", 30 | "properties": { 31 | "aesop.port": { 32 | "type": "number", 33 | "default": 8509, 34 | "description": "Port number" 35 | }, 36 | "aesop.host": { 37 | "type": "string", 38 | "default": "localhost", 39 | "description": "Host address" 40 | } 41 | } 42 | }, 43 | "keybindings": [ 44 | { 45 | "command": "extension.aesopAwaken", 46 | "key": "ctrl+k a", 47 | "mac": "cmd+k a" 48 | } 49 | ] 50 | }, 51 | "scripts": { 52 | "vscode:prepublish": "webpack --mode production", 53 | "webpack": "webpack --mode development", 54 | "webpack-dev": "webpack --mode development --watch", 55 | "test-compile": "tsc -p ./", 56 | "compile": "tsc -p ./", 57 | "watch": "tsc -watch -p ./", 58 | "pretest": "npm run compile", 59 | "test": "node ./out/test/runTest.js" 60 | }, 61 | "devDependencies": { 62 | "@types/express": "^4.17.2", 63 | "@types/glob": "^7.1.1", 64 | "@types/mocha": "^5.2.7", 65 | "@types/node": "^12.12.21", 66 | "@types/vscode": "^1.41.0", 67 | "glob": "^7.1.5", 68 | "mocha": "^10.2.0", 69 | "ts-loader": "^6.2.1", 70 | "tslint": "^5.20.0", 71 | "typescript": "^3.6.4", 72 | "vscode-test": "^1.2.2", 73 | "webpack": "^4.41.4", 74 | "webpack-cli": "^3.3.10" 75 | }, 76 | "dependencies": { 77 | "npm": "^6.14.6", 78 | "ps-node": "^0.1.6", 79 | "vsce": "^1.71.0" 80 | } 81 | } 82 | -------------------------------------------------------------------------------- /resources/Aesop128x128.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/storybookjs/vs-code-plugin/4e3eb00ad58c45b52fd5da4cb2e7e7e07c230dba/resources/Aesop128x128.png -------------------------------------------------------------------------------- /samples/React_Sample/.babelrc: -------------------------------------------------------------------------------- 1 | { 2 | "presets": ["@babel/preset-env", "@babel/preset-react"] 3 | } -------------------------------------------------------------------------------- /samples/React_Sample/.eslintrc.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | extends: [ 3 | "airbnb" 4 | ], 5 | env: { 6 | browser: true, 7 | node: true, 8 | es6: true, 9 | jest: true, 10 | }, 11 | rules: { 12 | "consistent-return": "off", 13 | "func-names": "off", 14 | "no-console": "off", 15 | "curly": "off", 16 | "react/destructuring-assignment": "off", 17 | "react/jsx-filename-extension": "off", 18 | "react/prop-types": "off", 19 | "react/jsx-wrap-multilines": "off", 20 | "react/jsx-one-expression-per-line": "off", 21 | "react/jsx-closing-tag-location": "off", 22 | } 23 | } -------------------------------------------------------------------------------- /samples/React_Sample/.storybook/config.js: -------------------------------------------------------------------------------- 1 | import { configure } from '@storybook/react'; 2 | import '../client/components/index.css'; 3 | 4 | configure(require.context('../client/components', true, /\.stories\.js$/), module); -------------------------------------------------------------------------------- /samples/React_Sample/client/components/CharacterCard.jsx: -------------------------------------------------------------------------------- 1 | /* eslint-disable camelcase, react/no-array-index-key, global-require, import/no-dynamic-require */ 2 | import React from 'react'; 3 | 4 | const CharacterCard = (info) => { 5 | const name = 'Luke Skywalker'; 6 | const height = '172'; 7 | const mass = '77'; 8 | const hair_color = 'blond'; 9 | const skin_color = 'fair'; 10 | const eye_color = 'blue'; 11 | const birth_year = '19BBY'; 12 | const gender = 'male'; 13 | 14 | return ( 15 |
16 |
17 |

{name}

18 |
19 | 28 |
29 | ); 30 | }; 31 | 32 | export default CharacterCard; 33 | -------------------------------------------------------------------------------- /samples/React_Sample/client/components/CharacterCard.stories.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import { storiesOf } from '@storybook/react'; 3 | 4 | 5 | import CharacterCard from './CharacterCard'; 6 | 7 | export default { 8 | component: CharacterCard, 9 | title: 'Character Card', 10 | // Our exports that end in "Data" are not stories. 11 | excludeStories: /.*Data$/, 12 | }; 13 | 14 | storiesOf('CharCard', module) 15 | .add('Luke Skywalker - CharCard', () => ) 16 | -------------------------------------------------------------------------------- /samples/React_Sample/client/components/CreateCharacter.jsx: -------------------------------------------------------------------------------- 1 | import React, { useState, useEffect } from 'react'; 2 | 3 | // requiring json data for use in dropdown and checkboxes 4 | const speciesData = require('../data/species.json'); 5 | const planetsData = require('../data/planets.json'); 6 | const filmsData = require('../data/films.json'); 7 | 8 | // Custom hook for handling input boxes 9 | // saves us from creating onChange handlers for them individually 10 | const useInput = init => { 11 | const [ value, setValue ] = useState(init); 12 | const onChange = e => { 13 | setValue(e.target.value); 14 | } 15 | // return the value with the onChange function instead of setValue function 16 | return [ value, onChange ]; 17 | } 18 | 19 | const CreateCharacter = props => { 20 | const [ name, nameOnChange ] = useInput(''); 21 | const [ gender, genderOnChange ] = useInput(''); 22 | const [ birth_year, birthYearOnChange ] = useInput(''); 23 | const [ eye_color, eyeColorOnChange ] = useInput(''); 24 | const [ skin_color, skinColorOnChange ] = useInput(''); 25 | const [ hair_color, hairColorOnChange ] = useInput(''); 26 | const [ mass, massOnChange ] = useInput(''); 27 | const [ height, heightOnChange ] = useInput(''); 28 | const [ species, setSpecies ] = useState(speciesData[0].name); 29 | const [ species_id, setSpeciesId ] = useState(speciesData[0]._id); 30 | const [ homeworld, setHomeworld ] = useState(planetsData[0].name); 31 | const [ homeworld_id, setHomeworldId ] = useState(planetsData[0]._id); 32 | const [ filmSet, setFilmSet ] = useState({}); 33 | const [ nameError, setNameError ] = useState(null); 34 | const [ heightError, setHeightError ] = useState(null); 35 | 36 | const handleSpeciesChange = e => { 37 | const idx = e.target.value; 38 | setSpecies(speciesData[idx].name); 39 | setSpeciesId(speciesData[idx]._id); 40 | } 41 | 42 | const handleHomeworldChange = e => { 43 | const idx = e.target.value; 44 | setHomeworld(planetsData[idx].name); 45 | setHomeworldId(planetsData[idx]._id); 46 | } 47 | 48 | const handleFilmCheck = e => { 49 | const idx = e.target.value; 50 | const newFilmSet = {...filmSet}; 51 | if (newFilmSet[idx]) delete newFilmSet[idx]; 52 | else newFilmSet[idx] = true; 53 | setFilmSet(newFilmSet); 54 | } 55 | 56 | const speciesOptions = speciesData.map((speciesObj, idx) => { 57 | return ( 58 | 59 | ) 60 | }); 61 | 62 | const homeworldOptions = planetsData.map((planetObj, idx) => { 63 | return ( 64 | 65 | ) 66 | }); 67 | 68 | const filmCheckboxes = filmsData.map((filmObj, idx) => { 69 | return ( 70 |
71 | 72 | {filmObj.title} 73 |
74 | ) 75 | }); 76 | 77 | return ( 78 |
79 |
80 |
81 |
82 |

Enter your character details

83 |
84 | 85 | 86 |
87 |
88 | 89 | 90 |
91 |
92 | 93 | 96 |
97 |
98 | 99 | 100 |
101 |
102 | 103 | 104 |
105 |
106 | 107 | 108 |
109 |
110 | 111 | 112 |
113 |
114 | 115 | 116 |
117 |
118 | 119 | 120 |
121 |
122 | 123 | 126 |
127 |
128 | 129 |
130 | {filmCheckboxes} 131 |
132 |
133 |
134 | 137 | 138 |
139 |
140 |
141 | ) 142 | } 143 | 144 | export default CreateCharacter; -------------------------------------------------------------------------------- /samples/React_Sample/client/components/CreateCharacter.stories.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import { storiesOf } from '@storybook/react'; 3 | 4 | import CreateCharacter from './CreateCharacter'; 5 | 6 | export default { 7 | component: CreateCharacter, 8 | title: 'Create Character Card', 9 | // Our exports that end in "Data" are not stories. 10 | excludeStories: /.*Data$/, 11 | }; 12 | 13 | storiesOf('Create Character', module) 14 | .add('Basic Character Creator Box', () => ) 15 | -------------------------------------------------------------------------------- /samples/React_Sample/client/components/Task.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | 3 | export default function Task({ task: { id, title, state }, onArchiveTask, onPinTask }) { 4 | return ( 5 |
6 | 15 |
16 | 17 |
18 |
event.stopPropagation()}> 19 | {state !== 'TASK_ARCHIVED' && ( 20 | onPinTask(id)}> 21 | 22 | 23 | )} 24 |
25 |
26 | ); 27 | } 28 | -------------------------------------------------------------------------------- /samples/React_Sample/client/components/Task.stories.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import { storiesOf } from '@storybook/react'; 3 | import { action } from '@storybook/addon-actions'; 4 | 5 | import Task from './Task'; 6 | 7 | export const task = { 8 | id: '1', 9 | title: 'Test Task', 10 | state: 'TASK_INBOX', 11 | updatedAt: new Date(2018, 0, 1, 9, 0), 12 | }; 13 | 14 | 15 | export const actions = { 16 | onPinTask: action('onPinTask'), 17 | onArchiveTask: action('onArchiveTask'), 18 | }; 19 | 20 | 21 | storiesOf('Task', module) 22 | .add('default', () => ) 23 | .add('pinned', () => ) 24 | .add('archived', () => ); -------------------------------------------------------------------------------- /samples/React_Sample/client/components/TaskList.js: -------------------------------------------------------------------------------- 1 | // src/components/TaskList.js 2 | 3 | import React from 'react'; 4 | 5 | import Task from './Task'; 6 | 7 | function TaskList({ loading, tasks, onPinTask, onArchiveTask }) { 8 | const events = { 9 | onPinTask, 10 | onArchiveTask, 11 | }; 12 | 13 | const LoadingRow = ( 14 |
15 | 16 | 17 | Loading cool state 18 | 19 |
20 | ); 21 | 22 | if (loading) { 23 | return ( 24 |
25 | {LoadingRow} 26 | {LoadingRow} 27 | {LoadingRow} 28 | {LoadingRow} 29 | {LoadingRow} 30 | {LoadingRow} 31 |
32 | ); 33 | } 34 | 35 | if (tasks.length === 0) { 36 | return ( 37 |
38 |
39 | 40 |
You have no tasks
41 |
Sit back and relax
42 |
43 |
44 | ); 45 | } 46 | 47 | const tasksInOrder = [ 48 | ...tasks.filter(t => t.state === 'TASK_PINNED'), 49 | ...tasks.filter(t => t.state !== 'TASK_PINNED'), 50 | ]; 51 | 52 | return ( 53 |
54 | {tasksInOrder.map(task => ( 55 | 56 | ))} 57 |
58 | ); 59 | } 60 | 61 | export default TaskList; -------------------------------------------------------------------------------- /samples/React_Sample/client/components/TaskList.stories.js: -------------------------------------------------------------------------------- 1 | // src/components/TaskList.stories.js 2 | 3 | import React from 'react'; 4 | 5 | import TaskList from './TaskList'; 6 | import { taskData, actionsData } from './Task.stories'; 7 | 8 | export default { 9 | component: TaskList, 10 | title: 'TaskList', 11 | decorators: [story =>
{story()}
], 12 | excludeStories: /.*Data$/, 13 | }; 14 | 15 | export const defaultTasksData = [ 16 | { ...taskData, id: '1', title: 'Task 1' }, 17 | { ...taskData, id: '2', title: 'Task 2' }, 18 | { ...taskData, id: '3', title: 'Task 3' }, 19 | { ...taskData, id: '4', title: 'Task 4' }, 20 | { ...taskData, id: '5', title: 'Task 5' }, 21 | { ...taskData, id: '6', title: 'Task 6' }, 22 | ]; 23 | 24 | export const withPinnedTasksData = [ 25 | ...defaultTasksData.slice(0, 5), 26 | { id: '6', title: 'Task 6 (pinned)', state: 'TASK_PINNED' }, 27 | ]; 28 | 29 | export const Default = () => ; 30 | 31 | export const WithPinnedTasks = () => ; 32 | 33 | export const Loading = () => ; 34 | 35 | export const Empty = () => ; -------------------------------------------------------------------------------- /samples/React_Sample/client/components/index.css: -------------------------------------------------------------------------------- 1 | @import url('https://fonts.googleapis.com/css?family=Nunito+Sans:400,400i,800'); 2 | html, 3 | body { 4 | margin: 0; 5 | padding: 0; 6 | } 7 | h1, 8 | h2, 9 | h3, 10 | h4, 11 | h5, 12 | h6, 13 | p, 14 | blockquote, 15 | pre, 16 | a, 17 | abbr, 18 | acronym, 19 | address, 20 | cite, 21 | code, 22 | del, 23 | dfn, 24 | em, 25 | img, 26 | q, 27 | s, 28 | samp, 29 | small, 30 | strike, 31 | strong, 32 | sub, 33 | sup, 34 | tt, 35 | var, 36 | dd, 37 | dl, 38 | dt, 39 | li, 40 | ol, 41 | ul, 42 | fieldset, 43 | form, 44 | label, 45 | legend, 46 | button, 47 | table, 48 | caption, 49 | tbody, 50 | tfoot, 51 | thead, 52 | tr, 53 | th, 54 | td { 55 | margin: 0; 56 | padding: 0; 57 | border: 0; 58 | font-weight: normal; 59 | font-style: normal; 60 | font-size: 100%; 61 | line-height: 1; 62 | font-family: inherit; 63 | } 64 | table { 65 | border-collapse: collapse; 66 | border-spacing: 0; 67 | } 68 | ol, 69 | ul { 70 | list-style: none; 71 | } 72 | q:before, 73 | q:after, 74 | blockquote:before, 75 | blockquote:after { 76 | content: ""; 77 | } 78 | html { 79 | font-size: 100%; 80 | -webkit-text-size-adjust: 100%; 81 | -ms-text-size-adjust: 100%; 82 | } 83 | a:focus { 84 | outline: thin dotted; 85 | } 86 | a:hover, 87 | a:active { 88 | outline: 0; 89 | } 90 | article, 91 | aside, 92 | details, 93 | figcaption, 94 | figure, 95 | footer, 96 | header, 97 | hgroup, 98 | nav, 99 | section { 100 | display: block; 101 | } 102 | audio, 103 | canvas, 104 | video { 105 | display: inline-block; 106 | *display: inline; 107 | *zoom: 1; 108 | } 109 | audio:not([controls]) { 110 | display: none; 111 | } 112 | sub, 113 | sup { 114 | font-size: 75%; 115 | line-height: 0; 116 | position: relative; 117 | vertical-align: baseline; 118 | } 119 | sup { 120 | top: -0.5em; 121 | } 122 | sub { 123 | bottom: -0.25em; 124 | } 125 | img { 126 | border: 0; 127 | -ms-interpolation-mode: bicubic; 128 | } 129 | button, 130 | input, 131 | select, 132 | textarea { 133 | font-size: 100%; 134 | margin: 0; 135 | vertical-align: baseline; 136 | *vertical-align: middle; 137 | } 138 | button, 139 | input { 140 | line-height: normal; 141 | *overflow: visible; 142 | } 143 | button::-moz-focus-inner, 144 | input::-moz-focus-inner { 145 | border: 0; 146 | padding: 0; 147 | } 148 | button, 149 | input[type="button"], 150 | input[type="reset"], 151 | input[type="submit"] { 152 | cursor: pointer; 153 | -webkit-appearance: button; 154 | } 155 | input[type="search"] { 156 | -webkit-appearance: textfield; 157 | -webkit-box-sizing: content-box; 158 | -moz-box-sizing: content-box; 159 | box-sizing: content-box; 160 | } 161 | input[type="search"]::-webkit-search-decoration { 162 | -webkit-appearance: none; 163 | } 164 | textarea { 165 | overflow: auto; 166 | vertical-align: top; 167 | } 168 | @keyframes spin { 169 | 0% { 170 | transform: rotate(0deg); 171 | } 172 | 100% { 173 | transform: rotate(359deg); 174 | } 175 | } 176 | @keyframes glow { 177 | 0%, 178 | 100% { 179 | opacity: 1; 180 | } 181 | 50% { 182 | opacity: 0.5; 183 | } 184 | } 185 | .force-wrap { 186 | word-wrap: break-word; 187 | word-break: break-all; 188 | -ms-word-break: break-all; 189 | word-break: break-word; 190 | hyphens: auto; 191 | } 192 | .type-light { 193 | font-family: 'Nunito Sans', "Helvetica Neue", Helvetica, Arial, sans-serif; 194 | font-weight: 300; 195 | } 196 | .type-bold { 197 | font-family: 'Nunito Sans', "Helvetica Neue", Helvetica, Arial, sans-serif; 198 | font-weight: 800; 199 | } 200 | .type-italic { 201 | font-family: 'Nunito Sans', "Helvetica Neue", Helvetica, Arial, sans-serif; 202 | font-weight: 400; 203 | font-style: italic; 204 | } 205 | * { 206 | box-sizing: border-box; 207 | -webkit-tap-highlight-color: rgba(0, 0, 0, 0); 208 | -webkit-tap-highlight-color: transparent; 209 | } 210 | html, 211 | button, 212 | input, 213 | textarea, 214 | select { 215 | outline: none; 216 | -webkit-font-smoothing: antialiased; 217 | -moz-osx-font-smoothing: grayscale; 218 | } 219 | body { 220 | font-family: 'Nunito Sans', "Helvetica Neue", Helvetica, Arial, sans-serif; 221 | font-style: 400; 222 | color: #333; 223 | font-size: 16px; 224 | background-color: #26c6da; 225 | } 226 | h1, 227 | h2, 228 | h3, 229 | h4, 230 | h5, 231 | h6 { 232 | font-family: 'Nunito Sans', "Helvetica Neue", Helvetica, Arial, sans-serif; 233 | font-style: 400; 234 | margin: 0; 235 | padding: 0; 236 | } 237 | h1 { 238 | font-size: 40px; 239 | line-height: 48px; 240 | } 241 | h2 { 242 | font-size: 28px; 243 | line-height: 32px; 244 | } 245 | h3 { 246 | font-size: 24px; 247 | line-height: 28px; 248 | } 249 | h4 { 250 | font-size: 20px; 251 | line-height: 24px; 252 | } 253 | h5 { 254 | font-size: 14px; 255 | line-height: 20px; 256 | color: #ccc; 257 | text-transform: uppercase; 258 | } 259 | h6 { 260 | color: #aaa; 261 | } 262 | p { 263 | font-size: 16px; 264 | line-height: 24px; 265 | } 266 | sub, 267 | sup { 268 | font-size: 0.8em; 269 | } 270 | sub { 271 | bottom: -0.2em; 272 | } 273 | sup { 274 | top: -0.2em; 275 | } 276 | b { 277 | font-weight: bold; 278 | } 279 | em { 280 | font-style: italic; 281 | } 282 | input[type="text"], 283 | input[type="email"], 284 | input[type="password"], 285 | textarea { 286 | font-size: 14px; 287 | line-height: 20px; 288 | font-family: 'Nunito Sans', "Helvetica Neue", Helvetica, Arial, sans-serif; 289 | font-style: 400; 290 | padding: .75rem 0; 291 | line-height: 1.5rem !important; 292 | border: none; 293 | border-radius: 0; 294 | box-sizing: border-box; 295 | color: #333; 296 | outline: none; 297 | } 298 | input[type="text"] ::placeholder, 299 | input[type="email"] ::placeholder, 300 | input[type="password"] ::placeholder, 301 | textarea ::placeholder { 302 | color: #778b91; 303 | } 304 | input[type="text"][disabled], 305 | input[type="email"][disabled], 306 | input[type="password"][disabled], 307 | textarea[disabled] { 308 | opacity: .5; 309 | } 310 | input:-webkit-autofill { 311 | -webkit-box-shadow: 0 0 0 1000px white inset; 312 | } 313 | .checkbox { 314 | display: inline-block; 315 | height: 3rem; 316 | position: relative; 317 | vertical-align: middle; 318 | width: 44px; 319 | } 320 | .checkbox input[type="checkbox"] { 321 | font-size: 1em; 322 | visibility: hidden; 323 | } 324 | .checkbox input[type="checkbox"] + span:before { 325 | position: absolute; 326 | top: 50%; 327 | right: auto; 328 | bottom: auto; 329 | left: 50%; 330 | width: 0.85em; 331 | height: 0.85em; 332 | transform: translate3d(-50%, -50%, 0); 333 | background: transparent; 334 | box-shadow: #2cc5d2 0 0 0 1px inset; 335 | content: ''; 336 | display: block; 337 | } 338 | .checkbox input[type="checkbox"]:checked + span:before { 339 | font-size: 16px; 340 | line-height: 24px; 341 | box-shadow: none; 342 | color: #2cc5d2; 343 | margin-top: -1px; 344 | font-family: 'percolate'; 345 | speak: none; 346 | font-style: normal; 347 | font-weight: normal; 348 | font-variant: normal; 349 | text-transform: none; 350 | line-height: 1; 351 | -webkit-font-smoothing: antialiased; 352 | -moz-osx-font-smoothing: grayscale; 353 | content: "\e65e"; 354 | } 355 | .input-symbol { 356 | display: inline-block; 357 | position: relative; 358 | } 359 | .input-symbol.error [class^="icon-"], 360 | .input-symbol.error [class*=" icon-"] { 361 | color: #ff4400; 362 | } 363 | .input-symbol [class^="icon-"], 364 | .input-symbol [class*=" icon-"] { 365 | left: 1em; 366 | } 367 | .input-symbol input { 368 | padding-left: 3em; 369 | } 370 | .input-symbol input { 371 | width: 100%; 372 | } 373 | .input-symbol input:focus + [class^="icon-"], 374 | .input-symbol input:focus + [class*=" icon-"] { 375 | color: #2cc5d2; 376 | } 377 | .input-symbol [class^="icon-"], 378 | .input-symbol [class*=" icon-"] { 379 | transition: all 300ms ease-in; 380 | transform: translate3d(0, -50%, 0); 381 | background: transparent; 382 | color: #aaa; 383 | font-size: 1em; 384 | height: 1em; 385 | position: absolute; 386 | top: 50%; 387 | width: 1em; 388 | } 389 | @font-face { 390 | font-family: "percolate"; 391 | src: url("/icon/percolate.eot?-5w3um4"); 392 | src: url("/icon/percolate.eot?#iefix5w3um4") format("embedded-opentype"), url("/icon/percolate.woff?5w3um4") format("woff"), url("/icon/percolate.ttf?5w3um4") format("truetype"), url("/icon/percolate.svg?5w3um4") format("svg"); 393 | font-weight: normal; 394 | font-style: normal; 395 | } 396 | [class^="icon-"], 397 | [class*=" icon-"] { 398 | font-family: "percolate"; 399 | speak: none; 400 | font-style: normal; 401 | font-weight: normal; 402 | font-variant: normal; 403 | text-transform: none; 404 | line-height: 1; 405 | /* Better Font Rendering =========== */ 406 | -webkit-font-smoothing: antialiased; 407 | -moz-osx-font-smoothing: grayscale; 408 | } 409 | .icon-graphql:before { 410 | content: "\e90a"; 411 | } 412 | .icon-redux:before { 413 | content: "\e908"; 414 | } 415 | .icon-grid:before { 416 | content: "\e909"; 417 | } 418 | .icon-redirect:before { 419 | content: "\e907"; 420 | } 421 | .icon-grow:before { 422 | content: "\e903"; 423 | } 424 | .icon-lightning:before { 425 | content: "\e904"; 426 | } 427 | .icon-request-change:before { 428 | content: "\e905"; 429 | } 430 | .icon-transfer:before { 431 | content: "\e906"; 432 | } 433 | .icon-calendar:before { 434 | content: "\e902"; 435 | } 436 | .icon-sidebar:before { 437 | content: "\e900"; 438 | } 439 | .icon-tablet:before { 440 | content: "\e901"; 441 | } 442 | .icon-atmosphere:before { 443 | content: "\e671"; 444 | } 445 | .icon-browser:before { 446 | content: "\e672"; 447 | } 448 | .icon-database:before { 449 | content: "\e673"; 450 | } 451 | .icon-expand-alt:before { 452 | content: "\e674"; 453 | } 454 | .icon-mobile:before { 455 | content: "\e675"; 456 | } 457 | .icon-watch:before { 458 | content: "\e676"; 459 | } 460 | .icon-home:before { 461 | content: "\e600"; 462 | } 463 | .icon-user-alt:before { 464 | content: "\e601"; 465 | } 466 | .icon-user:before { 467 | content: "\e602"; 468 | } 469 | .icon-user-add:before { 470 | content: "\e603"; 471 | } 472 | .icon-users:before { 473 | content: "\e604"; 474 | } 475 | .icon-profile:before { 476 | content: "\e605"; 477 | } 478 | .icon-bookmark:before { 479 | content: "\e606"; 480 | } 481 | .icon-bookmark-hollow:before { 482 | content: "\e607"; 483 | } 484 | .icon-star:before { 485 | content: "\e608"; 486 | } 487 | .icon-star-hollow:before { 488 | content: "\e609"; 489 | } 490 | .icon-circle:before { 491 | content: "\e60a"; 492 | } 493 | .icon-circle-hollow:before { 494 | content: "\e60b"; 495 | } 496 | .icon-heart:before { 497 | content: "\e60c"; 498 | } 499 | .icon-heart-hollow:before { 500 | content: "\e60d"; 501 | } 502 | .icon-face-happy:before { 503 | content: "\e60e"; 504 | } 505 | .icon-face-sad:before { 506 | content: "\e60f"; 507 | } 508 | .icon-face-neutral:before { 509 | content: "\e610"; 510 | } 511 | .icon-lock:before { 512 | content: "\e611"; 513 | } 514 | .icon-unlock:before { 515 | content: "\e612"; 516 | } 517 | .icon-key:before { 518 | content: "\e613"; 519 | } 520 | .icon-arrow-left-alt:before { 521 | content: "\e614"; 522 | } 523 | .icon-arrow-right-alt:before { 524 | content: "\e615"; 525 | } 526 | .icon-sync:before { 527 | content: "\e616"; 528 | } 529 | .icon-reply:before { 530 | content: "\e617"; 531 | } 532 | .icon-expand:before { 533 | content: "\e618"; 534 | } 535 | .icon-arrow-left:before { 536 | content: "\e619"; 537 | } 538 | .icon-arrow-up:before { 539 | content: "\e61a"; 540 | } 541 | .icon-arrow-down:before { 542 | content: "\e61b"; 543 | } 544 | .icon-arrow-right:before { 545 | content: "\e61c"; 546 | } 547 | .icon-chevron-down:before { 548 | content: "\e61d"; 549 | } 550 | .icon-back:before { 551 | content: "\e61e"; 552 | } 553 | .icon-download:before { 554 | content: "\e61f"; 555 | } 556 | .icon-upload:before { 557 | content: "\e620"; 558 | } 559 | .icon-proceed:before { 560 | content: "\e621"; 561 | } 562 | .icon-info:before { 563 | content: "\e622"; 564 | } 565 | .icon-question:before { 566 | content: "\e623"; 567 | } 568 | .icon-alert:before { 569 | content: "\e624"; 570 | } 571 | .icon-edit:before { 572 | content: "\e625"; 573 | } 574 | .icon-paintbrush:before { 575 | content: "\e626"; 576 | } 577 | .icon-close:before { 578 | content: "\e627"; 579 | } 580 | .icon-trash:before { 581 | content: "\e628"; 582 | } 583 | .icon-cross:before { 584 | content: "\e629"; 585 | } 586 | .icon-delete:before { 587 | content: "\e62a"; 588 | } 589 | .icon-power:before { 590 | content: "\e62b"; 591 | } 592 | .icon-add:before { 593 | content: "\e62c"; 594 | } 595 | .icon-plus:before { 596 | content: "\e62d"; 597 | } 598 | .icon-document:before { 599 | content: "\e62e"; 600 | } 601 | .icon-graph-line:before { 602 | content: "\e62f"; 603 | } 604 | .icon-doc-chart:before { 605 | content: "\e630"; 606 | } 607 | .icon-doc-list:before { 608 | content: "\e631"; 609 | } 610 | .icon-category:before { 611 | content: "\e632"; 612 | } 613 | .icon-copy:before { 614 | content: "\e633"; 615 | } 616 | .icon-book:before { 617 | content: "\e634"; 618 | } 619 | .icon-certificate:before { 620 | content: "\e636"; 621 | } 622 | .icon-print:before { 623 | content: "\e637"; 624 | } 625 | .icon-list-unordered:before { 626 | content: "\e638"; 627 | } 628 | .icon-graph-bar:before { 629 | content: "\e639"; 630 | } 631 | .icon-menu:before { 632 | content: "\e63a"; 633 | } 634 | .icon-filter:before { 635 | content: "\e63b"; 636 | } 637 | .icon-ellipsis:before { 638 | content: "\e63c"; 639 | } 640 | .icon-cog:before { 641 | content: "\e63d"; 642 | } 643 | .icon-wrench:before { 644 | content: "\e63e"; 645 | } 646 | .icon-nut:before { 647 | content: "\e63f"; 648 | } 649 | .icon-camera:before { 650 | content: "\e640"; 651 | } 652 | .icon-eye:before { 653 | content: "\e641"; 654 | } 655 | .icon-photo:before { 656 | content: "\e642"; 657 | } 658 | .icon-video:before { 659 | content: "\e643"; 660 | } 661 | .icon-speaker:before { 662 | content: "\e644"; 663 | } 664 | .icon-phone:before { 665 | content: "\e645"; 666 | } 667 | .icon-flag:before { 668 | content: "\e646"; 669 | } 670 | .icon-pin:before { 671 | content: "\e647"; 672 | } 673 | .icon-compass:before { 674 | content: "\e648"; 675 | } 676 | .icon-globe:before { 677 | content: "\e649"; 678 | } 679 | .icon-location:before { 680 | content: "\e64a"; 681 | } 682 | .icon-search:before { 683 | content: "\e64b"; 684 | } 685 | .icon-timer:before { 686 | content: "\e64c"; 687 | } 688 | .icon-time:before { 689 | content: "\e64d"; 690 | } 691 | .icon-dashboard:before { 692 | content: "\e64e"; 693 | } 694 | .icon-hourglass:before { 695 | content: "\e64f"; 696 | } 697 | .icon-play:before { 698 | content: "\e650"; 699 | } 700 | .icon-stop:before { 701 | content: "\e651"; 702 | } 703 | .icon-email:before { 704 | content: "\e652"; 705 | } 706 | .icon-comment:before { 707 | content: "\e653"; 708 | } 709 | .icon-link:before { 710 | content: "\e654"; 711 | } 712 | .icon-paperclip:before { 713 | content: "\e655"; 714 | } 715 | .icon-box:before { 716 | content: "\e656"; 717 | } 718 | .icon-structure:before { 719 | content: "\e657"; 720 | } 721 | .icon-commit:before { 722 | content: "\e658"; 723 | } 724 | .icon-cpu:before { 725 | content: "\e659"; 726 | } 727 | .icon-memory:before { 728 | content: "\e65a"; 729 | } 730 | .icon-outbox:before { 731 | content: "\e65b"; 732 | } 733 | .icon-share:before { 734 | content: "\e65c"; 735 | } 736 | .icon-button:before { 737 | content: "\e65d"; 738 | } 739 | .icon-check:before { 740 | content: "\e65e"; 741 | } 742 | .icon-form:before { 743 | content: "\e65f"; 744 | } 745 | .icon-admin:before { 746 | content: "\e660"; 747 | } 748 | .icon-paragraph:before { 749 | content: "\e661"; 750 | } 751 | .icon-bell:before { 752 | content: "\e662"; 753 | } 754 | .icon-rss:before { 755 | content: "\e663"; 756 | } 757 | .icon-basket:before { 758 | content: "\e664"; 759 | } 760 | .icon-credit:before { 761 | content: "\e665"; 762 | } 763 | .icon-support:before { 764 | content: "\e666"; 765 | } 766 | .icon-shield:before { 767 | content: "\e667"; 768 | } 769 | .icon-beaker:before { 770 | content: "\e668"; 771 | } 772 | .icon-google:before { 773 | content: "\e669"; 774 | } 775 | .icon-gdrive:before { 776 | content: "\e66a"; 777 | } 778 | .icon-youtube:before { 779 | content: "\e66b"; 780 | } 781 | .icon-facebook:before { 782 | content: "\e66c"; 783 | } 784 | .icon-thumbs-up:before { 785 | content: "\e66d"; 786 | } 787 | .icon-twitter:before { 788 | content: "\e66e"; 789 | } 790 | .icon-github:before { 791 | content: "\e66f"; 792 | } 793 | .icon-meteor:before { 794 | content: "\e670"; 795 | } 796 | a { 797 | transition: all 200ms ease-in; 798 | color: #5db9ff; 799 | cursor: pointer; 800 | text-decoration: none; 801 | } 802 | a:hover { 803 | color: #239da8; 804 | } 805 | a:active { 806 | color: #555; 807 | } 808 | a:focus { 809 | outline: none; 810 | } 811 | .list-heading { 812 | letter-spacing: .3em; 813 | text-indent: .3em; 814 | text-transform: uppercase; 815 | font-family: 'Nunito Sans', "Helvetica Neue", Helvetica, Arial, sans-serif; 816 | font-weight: 800; 817 | font-size: 11px; 818 | padding-left: 15px; 819 | line-height: 40px; 820 | background: #f8f8f8; 821 | color: #aaa; 822 | } 823 | .list-heading .icon-sync { 824 | opacity: 1; 825 | animation: spin 2s infinite linear; 826 | display: inline-block; 827 | margin-right: 4px; 828 | } 829 | .list-item { 830 | font-size: 14px; 831 | line-height: 20px; 832 | display: flex; 833 | flex-wrap: wrap; 834 | height: 3rem; 835 | max-width: 400px; 836 | background: white; 837 | transition: all ease-out 150ms; 838 | } 839 | .list-item .title { 840 | overflow: hidden; 841 | text-overflow: ellipsis; 842 | white-space: nowrap; 843 | flex: 1; 844 | } 845 | .list-item input[type="text"] { 846 | background: transparent; 847 | width: 400px; 848 | } 849 | .list-item input[type="text"]:focus { 850 | cursor: text; 851 | } 852 | .list-item .actions { 853 | transition: all 200ms ease-in; 854 | padding-right: 20px; 855 | } 856 | .list-item .actions a { 857 | display: inline-block; 858 | vertical-align: top; 859 | text-align: center; 860 | color: #eee; 861 | } 862 | .list-item .actions a:hover { 863 | color: #2cc5d2; 864 | } 865 | .list-item .actions a:active { 866 | color: #555; 867 | } 868 | .list-item .actions [class^="icon-"] { 869 | font-size: 16px; 870 | line-height: 24px; 871 | line-height: 3rem; 872 | text-align: center; 873 | } 874 | .list-item.TASK_PINNED .icon-star { 875 | color: #2cc5d2; 876 | } 877 | .list-item.TASK_ARCHIVED input[type="text"] { 878 | color: #aaa; 879 | } 880 | .list-item:hover { 881 | background-image: linear-gradient(to bottom, #e5f9f7 0%, #f0fffd 100%); 882 | } 883 | .list-item:hover .checkbox { 884 | cursor: pointer; 885 | } 886 | .list-item + .list-item { 887 | border-top: 1px solid #f0f9fb; 888 | } 889 | .list-item.checked input[type="text"] { 890 | color: #ccc; 891 | text-decoration: line-through; 892 | } 893 | .list-item.checked .delete-item { 894 | display: inline-block; 895 | } 896 | .loading-item { 897 | height: 3rem; 898 | max-width: 400px; 899 | background: white; 900 | display: flex; 901 | align-items: center; 902 | line-height: 1rem; 903 | padding-left: 16px; 904 | } 905 | .loading-item .glow-checkbox, 906 | .loading-item .glow-text span { 907 | animation: glow 1.5s ease-in-out infinite; 908 | background: #eee; 909 | max-width: 400px; 910 | color: transparent; 911 | cursor: progress; 912 | display: inline-block; 913 | } 914 | .loading-item .glow-checkbox { 915 | margin-right: 16px; 916 | width: 12px; 917 | height: 12px; 918 | } 919 | .loading-item + .loading-item { 920 | border-top: 1px solid #f0f9fb; 921 | } 922 | .list-items { 923 | position: relative; 924 | background: white; 925 | min-height: 222px; 926 | max-width: 400px; 927 | } 928 | .list-items .select-placeholder { 929 | border: none; 930 | width: 48px; 931 | } 932 | .wrapper-message { 933 | position: absolute; 934 | top: 45%; 935 | right: 0; 936 | bottom: auto; 937 | left: 0; 938 | width: auto; 939 | height: auto; 940 | transform: translate3d(0, -50%, 0); 941 | text-align: center; 942 | } 943 | .wrapper-message [class^="icon-"], 944 | .wrapper-message [class*=" icon-"] { 945 | font-size: 48px; 946 | line-height: 56px; 947 | color: #2cc5d2; 948 | display: block; 949 | } 950 | .wrapper-message .title-message { 951 | font-size: 16px; 952 | line-height: 24px; 953 | font-family: 'Nunito Sans', "Helvetica Neue", Helvetica, Arial, sans-serif; 954 | font-weight: 800; 955 | color: #555; 956 | } 957 | .wrapper-message .subtitle-message { 958 | font-size: 14px; 959 | line-height: 20px; 960 | color: #666; 961 | } 962 | .page.lists-show { 963 | min-height: 100vh; 964 | background: white; 965 | } 966 | .page.lists-show nav { 967 | background: #d3edf4; 968 | padding: 1.5rem 1.25rem; 969 | text-align: center; 970 | } 971 | @media screen and (min-width: 40em) { 972 | .page.lists-show nav { 973 | text-align: left; 974 | } 975 | } 976 | .page.lists-show nav .title-page { 977 | font-size: 20px; 978 | line-height: 24px; 979 | line-height: 2rem; 980 | cursor: pointer; 981 | white-space: nowrap; 982 | } 983 | .page.lists-show nav .title-page .title-wrapper { 984 | overflow: hidden; 985 | text-overflow: ellipsis; 986 | white-space: nowrap; 987 | font-family: 'Nunito Sans', "Helvetica Neue", Helvetica, Arial, sans-serif; 988 | font-weight: 800; 989 | color: #1c3f53; 990 | display: inline-block; 991 | vertical-align: top; 992 | max-width: 100%; 993 | } 994 | 995 | /* reset default styles */ 996 | *, 997 | *:before, 998 | *:after { 999 | box-sizing: inherit; 1000 | /* position: relative; */ 1001 | } 1002 | 1003 | *:focus { 1004 | outline: none !important; 1005 | box-shadow: none !important; 1006 | } 1007 | 1008 | html { 1009 | box-sizing: border-box; 1010 | font: 62.5% 'Source Sans Pro', sans-serif; 1011 | } 1012 | 1013 | a { 1014 | text-decoration: none; 1015 | } 1016 | 1017 | h1 { 1018 | font-size: 2.2rem; 1019 | } 1020 | 1021 | h2 { 1022 | font-size: 2rem; 1023 | } 1024 | 1025 | h3 { 1026 | font-size: 1.8rem; 1027 | } 1028 | 1029 | a, 1030 | p, 1031 | li, 1032 | button, 1033 | div { 1034 | font-size: 1.4rem; 1035 | } 1036 | 1037 | small { 1038 | font-size: 1.2rem; 1039 | } 1040 | 1041 | figure { 1042 | margin-block-start: 0; 1043 | margin-block-end: 0; 1044 | margin-inline-start: 0; 1045 | margin-inline-end: 0; 1046 | margin: 0; 1047 | } 1048 | 1049 | ul { 1050 | list-style: none; 1051 | padding-left: 0; 1052 | } 1053 | 1054 | button { 1055 | border-radius: 0; 1056 | background: transparent; 1057 | } 1058 | 1059 | 1060 | .mainSection { 1061 | margin-bottom: 5rem; 1062 | } 1063 | 1064 | /* page options */ 1065 | .charactersPageOptions { 1066 | display: flex; 1067 | flex-direction: row; 1068 | justify-content: center; 1069 | margin-top: 3rem; 1070 | } 1071 | 1072 | .charactersPageOptions button { 1073 | width: 100%; 1074 | max-width: 200px; 1075 | font-size: 14px; 1076 | padding: 1rem 1.5rem; 1077 | } 1078 | 1079 | .card { 1080 | color: black; 1081 | background: #f3f3f3; 1082 | padding: 2rem; 1083 | border: 1px solid lightgray; 1084 | box-shadow: 1px 1px 5px rgba(22, 22, 22, 0.915); 1085 | } 1086 | 1087 | /* button options */ 1088 | .btnMain { 1089 | color: #e4e4e4; 1090 | background: steelblue; 1091 | border: 1px solid steelblue; 1092 | padding: 0.5rem 1rem; 1093 | height: 3rem; 1094 | } 1095 | 1096 | .btnSecondary { 1097 | background: #f3f3f3; 1098 | padding: 0.5rem 1rem; 1099 | height: 3rem; 1100 | } 1101 | 1102 | .btnLg { 1103 | height: 5rem; 1104 | } 1105 | 1106 | /* character photo */ 1107 | .charPhoto { 1108 | max-width: 100%; 1109 | display: flex; 1110 | flex-direction: row; 1111 | } 1112 | 1113 | .charPhoto img { 1114 | width: 128px; 1115 | height: 128px; 1116 | } 1117 | 1118 | /* custom character styles */ 1119 | .customCharContainer { 1120 | display: flex; 1121 | flex-direction: column; 1122 | } 1123 | 1124 | .customizeChar { 1125 | max-width: 30rem; 1126 | width: 100%; 1127 | align-self: center; 1128 | } 1129 | 1130 | /* create character styles */ 1131 | .createCharContainer { 1132 | margin: 3rem; 1133 | } 1134 | 1135 | .createChar { 1136 | max-width: 25em; 1137 | width: 100%; 1138 | align-self: center; 1139 | } 1140 | 1141 | .createCharFields { 1142 | width: 100%; 1143 | display: flex; 1144 | margin-bottom: 0.2rem; 1145 | } 1146 | 1147 | .createCharFields label { 1148 | min-width: 8rem; 1149 | width: 9rem; 1150 | } 1151 | 1152 | .filmCheckboxContainer { 1153 | display: flex; 1154 | flex-direction: column; 1155 | } 1156 | 1157 | .checkboxLabel { 1158 | font-size: 1.2rem; 1159 | } 1160 | 1161 | .createCharButtonContainer { 1162 | margin-top: 1.5rem; 1163 | display: flex; 1164 | justify-content: space-between; 1165 | } 1166 | 1167 | .errorMsg { 1168 | color: red; 1169 | margin-left: 1rem; 1170 | font-size: 1.1rem; 1171 | padding-top: 0.2rem; 1172 | } 1173 | 1174 | /* nickname styles */ 1175 | .nicknameFields { 1176 | margin: 20px 0; 1177 | } 1178 | 1179 | .nicknameFields label { 1180 | display: block; 1181 | margin-bottom: 10px; 1182 | } 1183 | 1184 | .nicknameFields input { 1185 | padding: 15px 10px; 1186 | height: 14px; 1187 | max-width: 200px; 1188 | width: 100%; 1189 | font-size: 1.2rem; 1190 | } 1191 | 1192 | /* cards container */ 1193 | .charContainer { 1194 | padding: 10rem 10rem; 1195 | display: grid; 1196 | } 1197 | 1198 | /* character card container */ 1199 | .charCard { 1200 | max-width: 15em; 1201 | display: flex; 1202 | flex-direction: column; 1203 | justify-content: flex-start; 1204 | margin: 3rem; 1205 | } 1206 | 1207 | /* character card header */ 1208 | .charHeadContainer { 1209 | display: flex; 1210 | flex-direction: row; 1211 | align-items: center; 1212 | } 1213 | 1214 | .charHeadContainer div { 1215 | width: 100%; 1216 | } 1217 | 1218 | .charHeadContainer h3 { 1219 | margin: 0; 1220 | } 1221 | 1222 | .charHeadContainer .favIcon { 1223 | display: flex; 1224 | flex-direction: row; 1225 | justify-content: flex-end; 1226 | } 1227 | 1228 | /* character card photo */ 1229 | .charCard .charPhoto { 1230 | justify-content: center; 1231 | } 1232 | 1233 | /* character additional details - films */ 1234 | .charAddlDetail { 1235 | margin-top: 0; 1236 | margin-bottom: 0; 1237 | } 1238 | 1239 | .charFilmsList { 1240 | margin-top: 0; 1241 | } 1242 | 1243 | .charFilm { 1244 | margin-left: 0.5rem; 1245 | } 1246 | 1247 | /* character buttons */ 1248 | .charBtnOptions { 1249 | display: flex; 1250 | flex-direction: column; 1251 | justify-content: flex-end; 1252 | } 1253 | 1254 | .charBtnOptions .space { 1255 | margin-bottom: 1rem; 1256 | } 1257 | 1258 | .charBtnOptions button { 1259 | width: 100%; 1260 | } 1261 | -------------------------------------------------------------------------------- /samples/React_Sample/client/data/films.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "_id": 4, 4 | "title": "The Phantom Menace", 5 | "episode_id": 1, 6 | "opening_crawl": "Turmoil has engulfed the\nGalactic Republic. The taxation\nof trade routes to outlying star\nsystems is in dispute.\n\nHoping to resolve the matter\nwith a blockade of deadly\nbattleships, the greedy Trade\nFederation has stopped all\nshipping to the small planet\nof Naboo.\n\nWhile the Congress of the\nRepublic endlessly debates\nthis alarming chain of events,\nthe Supreme Chancellor has\nsecretly dispatched two Jedi\nKnights, the guardians of\npeace and justice in the\ngalaxy, to settle the conflict....", 7 | "director": "George Lucas", 8 | "producer": "Rick McCallum", 9 | "release_date": "1999-05-19T07:00:00.000Z" 10 | }, 11 | { 12 | "_id": 5, 13 | "title": "Attack of the Clones", 14 | "episode_id": 2, 15 | "opening_crawl": "There is unrest in the Galactic\nSenate. Several thousand solar\nsystems have declared their\nintentions to leave the Republic.\n\nThis separatist movement,\nunder the leadership of the\nmysterious Count Dooku, has\nmade it difficult for the limited\nnumber of Jedi Knights to maintain \npeace and order in the galaxy.\n\nSenator Amidala, the former\nQueen of Naboo, is returning\nto the Galactic Senate to vote\non the critical issue of creating\nan ARMY OF THE REPUBLIC\nto assist the overwhelmed\nJedi....", 16 | "director": "George Lucas", 17 | "producer": "Rick McCallum", 18 | "release_date": "2002-05-16T07:00:00.000Z" 19 | }, 20 | { 21 | "_id": 6, 22 | "title": "Revenge of the Sith", 23 | "episode_id": 3, 24 | "opening_crawl": "War! The Republic is crumbling\nunder attacks by the ruthless\nSith Lord, Count Dooku.\nThere are heroes on both sides.\nEvil is everywhere.\n\nIn a stunning move, the\nfiendish droid leader, General\nGrievous, has swept into the\nRepublic capital and kidnapped\nChancellor Palpatine, leader of\nthe Galactic Senate.\n\nAs the Separatist Droid Army\nattempts to flee the besieged\ncapital with their valuable\nhostage, two Jedi Knights lead a\ndesperate mission to rescue the\ncaptive Chancellor....", 25 | "director": "George Lucas", 26 | "producer": "Rick McCallum", 27 | "release_date": "2005-05-19T07:00:00.000Z" 28 | }, 29 | { 30 | "_id": 1, 31 | "title": "A New Hope", 32 | "episode_id": 4, 33 | "opening_crawl": "It is a period of civil war.\nRebel spaceships, striking\nfrom a hidden base, have won\ntheir first victory against\nthe evil Galactic Empire.\n\nDuring the battle, Rebel\nspies managed to steal secret\nplans to the Empire's\nultimate weapon, the DEATH\nSTAR, an armored space\nstation with enough power\nto destroy an entire planet.\n\nPursued by the Empire's\nsinister agents, Princess\nLeia races home aboard her\nstarship, custodian of the\nstolen plans that can save her\npeople and restore\nfreedom to the galaxy....", 34 | "director": "George Lucas", 35 | "producer": "Gary Kurtz, Rick McCallum", 36 | "release_date": "1977-05-25T07:00:00.000Z" 37 | }, 38 | { 39 | "_id": 2, 40 | "title": "The Empire Strikes Back", 41 | "episode_id": 5, 42 | "opening_crawl": "It is a dark time for the\nRebellion. Although the Death\nStar has been destroyed,\nImperial troops have driven the\nRebel forces from their hidden\nbase and pursued them across\nthe galaxy.\n\nEvading the dreaded Imperial\nStarfleet, a group of freedom\nfighters led by Luke Skywalker\nhas established a new secret\nbase on the remote ice world\nof Hoth.\n\nThe evil lord Darth Vader,\nobsessed with finding young\nSkywalker, has dispatched\nthousands of remote probes into\nthe far reaches of space....", 43 | "director": "Irvin Kershner", 44 | "producer": "Gary Kurtz, Rick McCallum", 45 | "release_date": "1980-05-17T07:00:00.000Z" 46 | }, 47 | { 48 | "_id": 3, 49 | "title": "Return of the Jedi", 50 | "episode_id": 6, 51 | "opening_crawl": "Luke Skywalker has returned to\nhis home planet of Tatooine in\nan attempt to rescue his\nfriend Han Solo from the\nclutches of the vile gangster\nJabba the Hutt.\n\nLittle does Luke know that the\nGALACTIC EMPIRE has secretly\nbegun construction on a new\narmored space station even\nmore powerful than the first\ndreaded Death Star.\n\nWhen completed, this ultimate\nweapon will spell certain doom\nfor the small band of rebels\nstruggling to restore freedom\nto the galaxy...", 52 | "director": "Richard Marquand", 53 | "producer": "Howard G. Kazanjian, George Lucas, Rick McCallum", 54 | "release_date": "1983-05-25T07:00:00.000Z" 55 | }, 56 | { 57 | "_id": 7, 58 | "title": "The Force Awakens", 59 | "episode_id": 7, 60 | "opening_crawl": "Luke Skywalker has vanished.\nIn his absence, the sinister\nFIRST ORDER has risen from\nthe ashes of the Empire\nand will not rest until\nSkywalker, the last Jedi,\nhas been destroyed.\n \nWith the support of the\nREPUBLIC, General Leia Organa\nleads a brave RESISTANCE.\nShe is desperate to find her\nbrother Luke and gain his\nhelp in restoring peace and\njustice to the galaxy.\n \nLeia has sent her most daring\npilot on a secret mission\nto Jakku, where an old ally\nhas discovered a clue to\nLuke's whereabouts....", 61 | "director": "J. J. Abrams", 62 | "producer": "Kathleen Kennedy, J. J. Abrams, Bryan Burk", 63 | "release_date": "2015-12-11T08:00:00.000Z" 64 | } 65 | ] -------------------------------------------------------------------------------- /samples/React_Sample/client/data/planets.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "_id": 2, 4 | "name": "Alderaan", 5 | "rotation_period": 24, 6 | "orbital_period": 364, 7 | "diameter": 12500, 8 | "climate": "temperate", 9 | "gravity": "1 standard", 10 | "terrain": "grasslands, mountains", 11 | "surface_water": "40", 12 | "population": "2000000000" 13 | }, 14 | { 15 | "_id": 38, 16 | "name": "Aleen Minor", 17 | "rotation_period": null, 18 | "orbital_period": null, 19 | "diameter": null, 20 | "climate": null, 21 | "gravity": null, 22 | "terrain": null, 23 | "surface_water": null, 24 | "population": null 25 | }, 26 | { 27 | "_id": 6, 28 | "name": "Bespin", 29 | "rotation_period": 12, 30 | "orbital_period": 5110, 31 | "diameter": 118000, 32 | "climate": "temperate", 33 | "gravity": "1.5 (surface), 1 standard (Cloud City)", 34 | "terrain": "gas giant", 35 | "surface_water": "0", 36 | "population": "6000000" 37 | }, 38 | { 39 | "_id": 43, 40 | "name": "Cerea", 41 | "rotation_period": 27, 42 | "orbital_period": 386, 43 | "diameter": null, 44 | "climate": "temperate", 45 | "gravity": "1", 46 | "terrain": "verdant", 47 | "surface_water": "20", 48 | "population": "450000000" 49 | }, 50 | { 51 | "_id": 50, 52 | "name": "Champala", 53 | "rotation_period": 27, 54 | "orbital_period": 318, 55 | "diameter": null, 56 | "climate": "temperate", 57 | "gravity": "1", 58 | "terrain": "oceans, rainforests, plateaus", 59 | "surface_water": null, 60 | "population": "3500000000" 61 | }, 62 | { 63 | "_id": 26, 64 | "name": "Bestine IV", 65 | "rotation_period": 26, 66 | "orbital_period": 680, 67 | "diameter": 6400, 68 | "climate": "temperate", 69 | "gravity": null, 70 | "terrain": "rocky islands, oceans", 71 | "surface_water": "98", 72 | "population": "62000000" 73 | }, 74 | { 75 | "_id": 18, 76 | "name": "Cato Neimoidia", 77 | "rotation_period": 25, 78 | "orbital_period": 278, 79 | "diameter": 0, 80 | "climate": "temperate, moist", 81 | "gravity": "1 standard", 82 | "terrain": "mountains, fields, forests, rock arches", 83 | "surface_water": null, 84 | "population": "10000000" 85 | }, 86 | { 87 | "_id": 32, 88 | "name": "Chandrila", 89 | "rotation_period": 20, 90 | "orbital_period": 368, 91 | "diameter": 13500, 92 | "climate": "temperate", 93 | "gravity": "1", 94 | "terrain": "plains, forests", 95 | "surface_water": "40", 96 | "population": "1200000000" 97 | }, 98 | { 99 | "_id": 53, 100 | "name": "Concord Dawn", 101 | "rotation_period": null, 102 | "orbital_period": null, 103 | "diameter": null, 104 | "climate": null, 105 | "gravity": null, 106 | "terrain": "jungles, forests, deserts", 107 | "surface_water": null, 108 | "population": null 109 | }, 110 | { 111 | "_id": 22, 112 | "name": "Corellia", 113 | "rotation_period": 25, 114 | "orbital_period": 329, 115 | "diameter": 11000, 116 | "climate": "temperate", 117 | "gravity": "1 standard", 118 | "terrain": "plains, urban, hills, forests", 119 | "surface_water": "70", 120 | "population": "3000000000" 121 | }, 122 | { 123 | "_id": 9, 124 | "name": "Coruscant", 125 | "rotation_period": 24, 126 | "orbital_period": 368, 127 | "diameter": 12240, 128 | "climate": "temperate", 129 | "gravity": "1 standard", 130 | "terrain": "cityscape, mountains", 131 | "surface_water": null, 132 | "population": "1000000000000" 133 | }, 134 | { 135 | "_id": 5, 136 | "name": "Dagobah", 137 | "rotation_period": 23, 138 | "orbital_period": 341, 139 | "diameter": 8900, 140 | "climate": "murky", 141 | "gravity": "N/A", 142 | "terrain": "swamp, jungles", 143 | "surface_water": "8", 144 | "population": null 145 | }, 146 | { 147 | "_id": 25, 148 | "name": "Dantooine", 149 | "rotation_period": 25, 150 | "orbital_period": 378, 151 | "diameter": 9830, 152 | "climate": "temperate", 153 | "gravity": "1 standard", 154 | "terrain": "oceans, savannas, mountains, grasslands", 155 | "surface_water": null, 156 | "population": "1000" 157 | }, 158 | { 159 | "_id": 36, 160 | "name": "Dathomir", 161 | "rotation_period": 24, 162 | "orbital_period": 491, 163 | "diameter": 10480, 164 | "climate": "temperate", 165 | "gravity": "0.9", 166 | "terrain": "forests, deserts, savannas", 167 | "surface_water": null, 168 | "population": "5200" 169 | }, 170 | { 171 | "_id": 49, 172 | "name": "Dorin", 173 | "rotation_period": 22, 174 | "orbital_period": 409, 175 | "diameter": 13400, 176 | "climate": "temperate", 177 | "gravity": "1", 178 | "terrain": null, 179 | "surface_water": null, 180 | "population": null 181 | }, 182 | { 183 | "_id": 7, 184 | "name": "Endor", 185 | "rotation_period": 18, 186 | "orbital_period": 402, 187 | "diameter": 4900, 188 | "climate": "temperate", 189 | "gravity": "0.85 standard", 190 | "terrain": "forests, mountains, lakes", 191 | "surface_water": "8", 192 | "population": "30000000" 193 | }, 194 | { 195 | "_id": 21, 196 | "name": "Eriadu", 197 | "rotation_period": 24, 198 | "orbital_period": 360, 199 | "diameter": 13490, 200 | "climate": "polluted", 201 | "gravity": "1 standard", 202 | "terrain": "cityscape", 203 | "surface_water": null, 204 | "population": "22000000000" 205 | }, 206 | { 207 | "_id": 17, 208 | "name": "Felucia", 209 | "rotation_period": 34, 210 | "orbital_period": 231, 211 | "diameter": 9100, 212 | "climate": "hot, humid", 213 | "gravity": "0.75 standard", 214 | "terrain": "fungus forests", 215 | "surface_water": null, 216 | "population": "8500000" 217 | }, 218 | { 219 | "_id": 11, 220 | "name": "Geonosis", 221 | "rotation_period": 30, 222 | "orbital_period": 256, 223 | "diameter": 11370, 224 | "climate": "temperate, arid", 225 | "gravity": "0.9 standard", 226 | "terrain": "rock, desert, mountain, barren", 227 | "surface_water": "5", 228 | "population": "100000000000" 229 | }, 230 | { 231 | "_id": 44, 232 | "name": "Glee Anselm", 233 | "rotation_period": 33, 234 | "orbital_period": 206, 235 | "diameter": 15600, 236 | "climate": "tropical, temperate", 237 | "gravity": "1", 238 | "terrain": "lakes, islands, swamps, seas", 239 | "surface_water": "80", 240 | "population": "500000000" 241 | }, 242 | { 243 | "_id": 42, 244 | "name": "Haruun Kal", 245 | "rotation_period": 25, 246 | "orbital_period": 383, 247 | "diameter": 10120, 248 | "climate": "temperate", 249 | "gravity": "0.98", 250 | "terrain": "toxic cloudsea, plateaus, volcanoes", 251 | "surface_water": null, 252 | "population": "705300" 253 | }, 254 | { 255 | "_id": 4, 256 | "name": "Hoth", 257 | "rotation_period": 23, 258 | "orbital_period": 549, 259 | "diameter": 7200, 260 | "climate": "frozen", 261 | "gravity": "1.1 standard", 262 | "terrain": "tundra, ice caves, mountain ranges", 263 | "surface_water": "100", 264 | "population": null 265 | }, 266 | { 267 | "_id": 47, 268 | "name": "Iktotch", 269 | "rotation_period": 22, 270 | "orbital_period": 481, 271 | "diameter": null, 272 | "climate": "arid, rocky, windy", 273 | "gravity": "1", 274 | "terrain": "rocky", 275 | "surface_water": null, 276 | "population": null 277 | }, 278 | { 279 | "_id": 45, 280 | "name": "Iridonia", 281 | "rotation_period": 29, 282 | "orbital_period": 413, 283 | "diameter": null, 284 | "climate": null, 285 | "gravity": null, 286 | "terrain": "rocky canyons, acid pools", 287 | "surface_water": null, 288 | "population": null 289 | }, 290 | { 291 | "_id": 61, 292 | "name": "Jakku", 293 | "rotation_period": null, 294 | "orbital_period": null, 295 | "diameter": null, 296 | "climate": null, 297 | "gravity": null, 298 | "terrain": "deserts", 299 | "surface_water": null, 300 | "population": null 301 | }, 302 | { 303 | "_id": 59, 304 | "name": "Kalee", 305 | "rotation_period": 23, 306 | "orbital_period": 378, 307 | "diameter": 13850, 308 | "climate": "arid, temperate, tropical", 309 | "gravity": "1", 310 | "terrain": "rainforests, cliffs, canyons, seas", 311 | "surface_water": null, 312 | "population": "4000000000" 313 | }, 314 | { 315 | "_id": 10, 316 | "name": "Kamino", 317 | "rotation_period": 27, 318 | "orbital_period": 463, 319 | "diameter": 19720, 320 | "climate": "temperate", 321 | "gravity": "1 standard", 322 | "terrain": "ocean", 323 | "surface_water": "100", 324 | "population": "1000000000" 325 | }, 326 | { 327 | "_id": 14, 328 | "name": "Kashyyyk", 329 | "rotation_period": 26, 330 | "orbital_period": 381, 331 | "diameter": 12765, 332 | "climate": "tropical", 333 | "gravity": "1 standard", 334 | "terrain": "jungle, forests, lakes, rivers", 335 | "surface_water": "60", 336 | "population": "45000000" 337 | }, 338 | { 339 | "_id": 35, 340 | "name": "Malastare", 341 | "rotation_period": 26, 342 | "orbital_period": 201, 343 | "diameter": 18880, 344 | "climate": "arid, temperate, tropical", 345 | "gravity": "1.56", 346 | "terrain": "swamps, deserts, jungles, mountains", 347 | "surface_water": null, 348 | "population": "2000000000" 349 | }, 350 | { 351 | "_id": 51, 352 | "name": "Mirial", 353 | "rotation_period": null, 354 | "orbital_period": null, 355 | "diameter": null, 356 | "climate": null, 357 | "gravity": null, 358 | "terrain": "deserts", 359 | "surface_water": null, 360 | "population": null 361 | }, 362 | { 363 | "_id": 31, 364 | "name": "Mon Cala", 365 | "rotation_period": 21, 366 | "orbital_period": 398, 367 | "diameter": 11030, 368 | "climate": "temperate", 369 | "gravity": "1", 370 | "terrain": "oceans, reefs, islands", 371 | "surface_water": "100", 372 | "population": "27000000000" 373 | }, 374 | { 375 | "_id": 13, 376 | "name": "Mustafar", 377 | "rotation_period": 36, 378 | "orbital_period": 412, 379 | "diameter": 4200, 380 | "climate": "hot", 381 | "gravity": "1 standard", 382 | "terrain": "volcanoes, lava rivers, mountains, caves", 383 | "surface_water": "0", 384 | "population": "20000" 385 | }, 386 | { 387 | "_id": 57, 388 | "name": "Muunilinst", 389 | "rotation_period": 28, 390 | "orbital_period": 412, 391 | "diameter": 13800, 392 | "climate": "temperate", 393 | "gravity": "1", 394 | "terrain": "plains, forests, hills, mountains", 395 | "surface_water": "25", 396 | "population": "5000000000" 397 | }, 398 | { 399 | "_id": 16, 400 | "name": "Mygeeto", 401 | "rotation_period": 12, 402 | "orbital_period": 167, 403 | "diameter": 10088, 404 | "climate": "frigid", 405 | "gravity": "1 standard", 406 | "terrain": "glaciers, mountains, ice canyons", 407 | "surface_water": null, 408 | "population": "19000000" 409 | }, 410 | { 411 | "_id": 8, 412 | "name": "Naboo", 413 | "rotation_period": 26, 414 | "orbital_period": 312, 415 | "diameter": 12120, 416 | "climate": "temperate", 417 | "gravity": "1 standard", 418 | "terrain": "grassy hills, swamps, forests, mountains", 419 | "surface_water": "12", 420 | "population": "4500000000" 421 | }, 422 | { 423 | "_id": 24, 424 | "name": "Nal Hutta", 425 | "rotation_period": 87, 426 | "orbital_period": 413, 427 | "diameter": 12150, 428 | "climate": "temperate", 429 | "gravity": "1 standard", 430 | "terrain": "urban, oceans, swamps, bogs", 431 | "surface_water": null, 432 | "population": "7000000000" 433 | }, 434 | { 435 | "_id": 55, 436 | "name": "Ojom", 437 | "rotation_period": null, 438 | "orbital_period": null, 439 | "diameter": null, 440 | "climate": "frigid", 441 | "gravity": null, 442 | "terrain": "oceans, glaciers", 443 | "surface_water": "100", 444 | "population": "500000000" 445 | }, 446 | { 447 | "_id": 27, 448 | "name": "Ord Mantell", 449 | "rotation_period": 26, 450 | "orbital_period": 334, 451 | "diameter": 14050, 452 | "climate": "temperate", 453 | "gravity": "1 standard", 454 | "terrain": "plains, seas, mesas", 455 | "surface_water": "10", 456 | "population": "4000000000" 457 | }, 458 | { 459 | "_id": 15, 460 | "name": "Polis Massa", 461 | "rotation_period": 24, 462 | "orbital_period": 590, 463 | "diameter": 0, 464 | "climate": "artificial temperate ", 465 | "gravity": "0.56 standard", 466 | "terrain": "airless asteroid", 467 | "surface_water": "0", 468 | "population": "1000000" 469 | }, 470 | { 471 | "_id": 48, 472 | "name": "Quermia", 473 | "rotation_period": null, 474 | "orbital_period": null, 475 | "diameter": null, 476 | "climate": null, 477 | "gravity": null, 478 | "terrain": null, 479 | "surface_water": null, 480 | "population": null 481 | }, 482 | { 483 | "_id": 23, 484 | "name": "Rodia", 485 | "rotation_period": 29, 486 | "orbital_period": 305, 487 | "diameter": 7549, 488 | "climate": "hot", 489 | "gravity": "1 standard", 490 | "terrain": "jungles, oceans, urban, swamps", 491 | "surface_water": "60", 492 | "population": "1300000000" 493 | }, 494 | { 495 | "_id": 37, 496 | "name": "Ryloth", 497 | "rotation_period": 30, 498 | "orbital_period": 305, 499 | "diameter": 10600, 500 | "climate": "temperate, arid, subartic", 501 | "gravity": "1", 502 | "terrain": "mountains, valleys, deserts, tundra", 503 | "surface_water": "5", 504 | "population": "1500000000" 505 | }, 506 | { 507 | "_id": 19, 508 | "name": "Saleucami", 509 | "rotation_period": 26, 510 | "orbital_period": 392, 511 | "diameter": 14920, 512 | "climate": "hot", 513 | "gravity": null, 514 | "terrain": "caves, desert, mountains, volcanoes", 515 | "surface_water": null, 516 | "population": "1400000000" 517 | }, 518 | { 519 | "_id": 52, 520 | "name": "Serenno", 521 | "rotation_period": null, 522 | "orbital_period": null, 523 | "diameter": null, 524 | "climate": null, 525 | "gravity": null, 526 | "terrain": "rainforests, rivers, mountains", 527 | "surface_water": null, 528 | "population": null 529 | }, 530 | { 531 | "_id": 58, 532 | "name": "Shili", 533 | "rotation_period": null, 534 | "orbital_period": null, 535 | "diameter": null, 536 | "climate": "temperate", 537 | "gravity": "1", 538 | "terrain": "cities, savannahs, seas, plains", 539 | "surface_water": null, 540 | "population": null 541 | }, 542 | { 543 | "_id": 56, 544 | "name": "Skako", 545 | "rotation_period": 27, 546 | "orbital_period": 384, 547 | "diameter": null, 548 | "climate": "temperate", 549 | "gravity": "1", 550 | "terrain": "urban, vines", 551 | "surface_water": null, 552 | "population": "500000000000" 553 | }, 554 | { 555 | "_id": 30, 556 | "name": "Socorro", 557 | "rotation_period": 20, 558 | "orbital_period": 326, 559 | "diameter": 0, 560 | "climate": "arid", 561 | "gravity": "1 standard", 562 | "terrain": "deserts, mountains", 563 | "surface_water": null, 564 | "population": "300000000" 565 | }, 566 | { 567 | "_id": 20, 568 | "name": "Stewjon", 569 | "rotation_period": null, 570 | "orbital_period": null, 571 | "diameter": 0, 572 | "climate": "temperate", 573 | "gravity": "1 standard", 574 | "terrain": "grass", 575 | "surface_water": null, 576 | "population": null 577 | }, 578 | { 579 | "_id": 33, 580 | "name": "Sullust", 581 | "rotation_period": 20, 582 | "orbital_period": 263, 583 | "diameter": 12780, 584 | "climate": "superheated", 585 | "gravity": "1", 586 | "terrain": "mountains, volcanoes, rocky deserts", 587 | "surface_water": "5", 588 | "population": "18500000000" 589 | }, 590 | { 591 | "_id": 1, 592 | "name": "Tatooine", 593 | "rotation_period": 23, 594 | "orbital_period": 304, 595 | "diameter": 10465, 596 | "climate": "arid", 597 | "gravity": "1 standard", 598 | "terrain": "desert", 599 | "surface_water": "1", 600 | "population": "200000" 601 | }, 602 | { 603 | "_id": 46, 604 | "name": "Tholoth", 605 | "rotation_period": null, 606 | "orbital_period": null, 607 | "diameter": null, 608 | "climate": null, 609 | "gravity": null, 610 | "terrain": null, 611 | "surface_water": null, 612 | "population": null 613 | }, 614 | { 615 | "_id": 34, 616 | "name": "Toydaria", 617 | "rotation_period": 21, 618 | "orbital_period": 184, 619 | "diameter": 7900, 620 | "climate": "temperate", 621 | "gravity": "1", 622 | "terrain": "swamps, lakes", 623 | "surface_water": null, 624 | "population": "11000000" 625 | }, 626 | { 627 | "_id": 29, 628 | "name": "Trandosha", 629 | "rotation_period": 25, 630 | "orbital_period": 371, 631 | "diameter": 0, 632 | "climate": "arid", 633 | "gravity": "0.62 standard", 634 | "terrain": "mountains, seas, grasslands, deserts", 635 | "surface_water": null, 636 | "population": "42000000" 637 | }, 638 | { 639 | "_id": 40, 640 | "name": "Troiken", 641 | "rotation_period": null, 642 | "orbital_period": null, 643 | "diameter": null, 644 | "climate": null, 645 | "gravity": null, 646 | "terrain": "desert, tundra, rainforests, mountains", 647 | "surface_water": null, 648 | "population": null 649 | }, 650 | { 651 | "_id": 41, 652 | "name": "Tund", 653 | "rotation_period": 48, 654 | "orbital_period": 1770, 655 | "diameter": 12190, 656 | "climate": null, 657 | "gravity": null, 658 | "terrain": "barren, ash", 659 | "surface_water": null, 660 | "population": "0" 661 | }, 662 | { 663 | "_id": 60, 664 | "name": "Umbara", 665 | "rotation_period": null, 666 | "orbital_period": null, 667 | "diameter": null, 668 | "climate": null, 669 | "gravity": null, 670 | "terrain": null, 671 | "surface_water": null, 672 | "population": null 673 | }, 674 | { 675 | "_id": 12, 676 | "name": "Utapau", 677 | "rotation_period": 27, 678 | "orbital_period": 351, 679 | "diameter": 12900, 680 | "climate": "temperate, arid, windy", 681 | "gravity": "1 standard", 682 | "terrain": "scrublands, savanna, canyons, sinkholes", 683 | "surface_water": "0.9", 684 | "population": "95000000" 685 | }, 686 | { 687 | "_id": 39, 688 | "name": "Vulpter", 689 | "rotation_period": 22, 690 | "orbital_period": 391, 691 | "diameter": 14900, 692 | "climate": "temperate, artic", 693 | "gravity": "1", 694 | "terrain": "urban, barren", 695 | "surface_water": null, 696 | "population": "421000000" 697 | }, 698 | { 699 | "_id": 3, 700 | "name": "Yavin IV", 701 | "rotation_period": 24, 702 | "orbital_period": 4818, 703 | "diameter": 10200, 704 | "climate": "temperate, tropical", 705 | "gravity": "1 standard", 706 | "terrain": "jungle, rainforests", 707 | "surface_water": "8", 708 | "population": "1000" 709 | }, 710 | { 711 | "_id": 54, 712 | "name": "Zolan", 713 | "rotation_period": null, 714 | "orbital_period": null, 715 | "diameter": null, 716 | "climate": null, 717 | "gravity": null, 718 | "terrain": null, 719 | "surface_water": null, 720 | "population": null 721 | } 722 | ] -------------------------------------------------------------------------------- /samples/React_Sample/client/data/species.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "_id": 16, 4 | "name": "Aleena", 5 | "classification": "reptile", 6 | "average_height": "80", 7 | "average_lifespan": "79", 8 | "hair_colors": "none", 9 | "skin_colors": "blue, gray", 10 | "eye_colors": "unknown", 11 | "language": "Aleena", 12 | "homeworld_id": "38" 13 | }, 14 | { 15 | "_id": 31, 16 | "name": "Besalisk", 17 | "classification": "amphibian", 18 | "average_height": "178", 19 | "average_lifespan": "75", 20 | "hair_colors": "none", 21 | "skin_colors": "brown", 22 | "eye_colors": "yellow", 23 | "language": "besalisk", 24 | "homeworld_id": "55" 25 | }, 26 | { 27 | "_id": 20, 28 | "name": "Cerean", 29 | "classification": "mammal", 30 | "average_height": "200", 31 | "average_lifespan": "unknown", 32 | "hair_colors": "red, blond, black, white", 33 | "skin_colors": "pale pink", 34 | "eye_colors": "hazel", 35 | "language": "Cerean", 36 | "homeworld_id": "43" 37 | }, 38 | { 39 | "_id": 27, 40 | "name": "Chagrian", 41 | "classification": "amphibian", 42 | "average_height": "190", 43 | "average_lifespan": "unknown", 44 | "hair_colors": "none", 45 | "skin_colors": "blue", 46 | "eye_colors": "blue", 47 | "language": "Chagria", 48 | "homeworld_id": "50" 49 | }, 50 | { 51 | "_id": 30, 52 | "name": "Clawdite", 53 | "classification": "reptilian", 54 | "average_height": "180", 55 | "average_lifespan": "70", 56 | "hair_colors": "none", 57 | "skin_colors": "green, yellow", 58 | "eye_colors": "yellow", 59 | "language": "Clawdite", 60 | "homeworld_id": "54" 61 | }, 62 | { 63 | "_id": 2, 64 | "name": "Droid", 65 | "classification": "artificial", 66 | "average_height": "n/a", 67 | "average_lifespan": "indefinite", 68 | "hair_colors": "n/a", 69 | "skin_colors": "n/a", 70 | "eye_colors": "n/a", 71 | "language": "n/a", 72 | "homeworld_id": null 73 | }, 74 | { 75 | "_id": 14, 76 | "name": "Dug", 77 | "classification": "mammal", 78 | "average_height": "100", 79 | "average_lifespan": "unknown", 80 | "hair_colors": "none", 81 | "skin_colors": "brown, purple, grey, red", 82 | "eye_colors": "yellow, blue", 83 | "language": "Dugese", 84 | "homeworld_id": "35" 85 | }, 86 | { 87 | "_id": 9, 88 | "name": "Ewok", 89 | "classification": "mammal", 90 | "average_height": "100", 91 | "average_lifespan": "unknown", 92 | "hair_colors": "white, brown, black", 93 | "skin_colors": "brown", 94 | "eye_colors": "orange, brown", 95 | "language": "Ewokese", 96 | "homeworld_id": "7" 97 | }, 98 | { 99 | "_id": 28, 100 | "name": "Geonosian", 101 | "classification": "insectoid", 102 | "average_height": "178", 103 | "average_lifespan": "unknown", 104 | "hair_colors": "none", 105 | "skin_colors": "green, brown", 106 | "eye_colors": "green, hazel", 107 | "language": "Geonosian", 108 | "homeworld_id": "11" 109 | }, 110 | { 111 | "_id": 12, 112 | "name": "Gungan", 113 | "classification": "amphibian", 114 | "average_height": "190", 115 | "average_lifespan": "unknown", 116 | "hair_colors": "none", 117 | "skin_colors": "brown, green", 118 | "eye_colors": "orange", 119 | "language": "Gungan basic", 120 | "homeworld_id": "8" 121 | }, 122 | { 123 | "_id": 1, 124 | "name": "Human", 125 | "classification": "mammal", 126 | "average_height": "180", 127 | "average_lifespan": "120", 128 | "hair_colors": "blonde, brown, black, red", 129 | "skin_colors": "caucasian, black, asian, hispanic", 130 | "eye_colors": "brown, blue, green, hazel, grey, amber", 131 | "language": "Galactic Basic", 132 | "homeworld_id": "9" 133 | }, 134 | { 135 | "_id": 5, 136 | "name": "Hutt", 137 | "classification": "gastropod", 138 | "average_height": "300", 139 | "average_lifespan": "1000", 140 | "hair_colors": "n/a", 141 | "skin_colors": "green, brown, tan", 142 | "eye_colors": "yellow, red", 143 | "language": "Huttese", 144 | "homeworld_id": "24" 145 | }, 146 | { 147 | "_id": 24, 148 | "name": "Iktotchi", 149 | "classification": "unknown", 150 | "average_height": "180", 151 | "average_lifespan": "unknown", 152 | "hair_colors": "none", 153 | "skin_colors": "pink", 154 | "eye_colors": "orange", 155 | "language": "Iktotchese", 156 | "homeworld_id": "47" 157 | }, 158 | { 159 | "_id": 36, 160 | "name": "Kaleesh", 161 | "classification": "reptile", 162 | "average_height": "170", 163 | "average_lifespan": "80", 164 | "hair_colors": "none", 165 | "skin_colors": "brown, orange, tan", 166 | "eye_colors": "yellow", 167 | "language": "Kaleesh", 168 | "homeworld_id": "59" 169 | }, 170 | { 171 | "_id": 32, 172 | "name": "Kaminoan", 173 | "classification": "amphibian", 174 | "average_height": "220", 175 | "average_lifespan": "80", 176 | "hair_colors": "none", 177 | "skin_colors": "grey, blue", 178 | "eye_colors": "black", 179 | "language": "Kaminoan", 180 | "homeworld_id": "10" 181 | }, 182 | { 183 | "_id": 26, 184 | "name": "Kel Dor", 185 | "classification": "unknown", 186 | "average_height": "180", 187 | "average_lifespan": "70", 188 | "hair_colors": "none", 189 | "skin_colors": "peach, orange, red", 190 | "eye_colors": "black, silver", 191 | "language": "Kel Dor", 192 | "homeworld_id": "49" 193 | }, 194 | { 195 | "_id": 29, 196 | "name": "Mirialan", 197 | "classification": "mammal", 198 | "average_height": "180", 199 | "average_lifespan": "unknown", 200 | "hair_colors": "black, brown", 201 | "skin_colors": "yellow, green", 202 | "eye_colors": "blue, green, red, yellow, brown, orange", 203 | "language": "Mirialan", 204 | "homeworld_id": "51" 205 | }, 206 | { 207 | "_id": 8, 208 | "name": "Mon Calamari", 209 | "classification": "amphibian", 210 | "average_height": "160", 211 | "average_lifespan": "unknown", 212 | "hair_colors": "none", 213 | "skin_colors": "red, blue, brown, magenta", 214 | "eye_colors": "yellow", 215 | "language": "Mon Calamarian", 216 | "homeworld_id": "31" 217 | }, 218 | { 219 | "_id": 34, 220 | "name": "Muun", 221 | "classification": "mammal", 222 | "average_height": "190", 223 | "average_lifespan": "100", 224 | "hair_colors": "none", 225 | "skin_colors": "grey, white", 226 | "eye_colors": "black", 227 | "language": "Muun", 228 | "homeworld_id": "57" 229 | }, 230 | { 231 | "_id": 21, 232 | "name": "Nautolan", 233 | "classification": "amphibian", 234 | "average_height": "180", 235 | "average_lifespan": "70", 236 | "hair_colors": "none", 237 | "skin_colors": "green, blue, brown, red", 238 | "eye_colors": "black", 239 | "language": "Nautila", 240 | "homeworld_id": "44" 241 | }, 242 | { 243 | "_id": 11, 244 | "name": "Neimodian", 245 | "classification": "unknown", 246 | "average_height": "180", 247 | "average_lifespan": "unknown", 248 | "hair_colors": "none", 249 | "skin_colors": "grey, green", 250 | "eye_colors": "red, pink", 251 | "language": "Neimoidia", 252 | "homeworld_id": "18" 253 | }, 254 | { 255 | "_id": 37, 256 | "name": "Pau'an", 257 | "classification": "mammal", 258 | "average_height": "190", 259 | "average_lifespan": "700", 260 | "hair_colors": "none", 261 | "skin_colors": "grey", 262 | "eye_colors": "black", 263 | "language": "Utapese", 264 | "homeworld_id": "12" 265 | }, 266 | { 267 | "_id": 25, 268 | "name": "Quermian", 269 | "classification": "mammal", 270 | "average_height": "240", 271 | "average_lifespan": "86", 272 | "hair_colors": "none", 273 | "skin_colors": "white", 274 | "eye_colors": "yellow", 275 | "language": "Quermian", 276 | "homeworld_id": "48" 277 | }, 278 | { 279 | "_id": 4, 280 | "name": "Rodian", 281 | "classification": "sentient", 282 | "average_height": "170", 283 | "average_lifespan": "unknown", 284 | "hair_colors": "n/a", 285 | "skin_colors": "green, blue", 286 | "eye_colors": "black", 287 | "language": "Galactic Basic", 288 | "homeworld_id": "23" 289 | }, 290 | { 291 | "_id": 33, 292 | "name": "Skakoan", 293 | "classification": "mammal", 294 | "average_height": "unknown", 295 | "average_lifespan": "unknown", 296 | "hair_colors": "none", 297 | "skin_colors": "grey, green", 298 | "eye_colors": "unknown", 299 | "language": "Skakoan", 300 | "homeworld_id": "56" 301 | }, 302 | { 303 | "_id": 10, 304 | "name": "Sullustan", 305 | "classification": "mammal", 306 | "average_height": "180", 307 | "average_lifespan": "unknown", 308 | "hair_colors": "none", 309 | "skin_colors": "pale", 310 | "eye_colors": "black", 311 | "language": "Sullutese", 312 | "homeworld_id": "33" 313 | }, 314 | { 315 | "_id": 23, 316 | "name": "Tholothian", 317 | "classification": "mammal", 318 | "average_height": "unknown", 319 | "average_lifespan": "unknown", 320 | "hair_colors": "unknown", 321 | "skin_colors": "dark", 322 | "eye_colors": "blue, indigo", 323 | "language": "unknown", 324 | "homeworld_id": "46" 325 | }, 326 | { 327 | "_id": 35, 328 | "name": "Togruta", 329 | "classification": "mammal", 330 | "average_height": "180", 331 | "average_lifespan": "94", 332 | "hair_colors": "none", 333 | "skin_colors": "red, white, orange, yellow, green, blue", 334 | "eye_colors": "red, orange, yellow, green, blue, black", 335 | "language": "Togruti", 336 | "homeworld_id": "58" 337 | }, 338 | { 339 | "_id": 19, 340 | "name": "Toong", 341 | "classification": "unknown", 342 | "average_height": "200", 343 | "average_lifespan": "unknown", 344 | "hair_colors": "none", 345 | "skin_colors": "grey, green, yellow", 346 | "eye_colors": "orange", 347 | "language": "Tundan", 348 | "homeworld_id": "41" 349 | }, 350 | { 351 | "_id": 13, 352 | "name": "Toydarian", 353 | "classification": "mammal", 354 | "average_height": "120", 355 | "average_lifespan": "91", 356 | "hair_colors": "none", 357 | "skin_colors": "blue, green, grey", 358 | "eye_colors": "yellow", 359 | "language": "Toydarian", 360 | "homeworld_id": "34" 361 | }, 362 | { 363 | "_id": 7, 364 | "name": "Trandoshan", 365 | "classification": "reptile", 366 | "average_height": "200", 367 | "average_lifespan": "unknown", 368 | "hair_colors": "none", 369 | "skin_colors": "brown, green", 370 | "eye_colors": "yellow, orange", 371 | "language": "Dosh", 372 | "homeworld_id": "29" 373 | }, 374 | { 375 | "_id": 15, 376 | "name": "Twi'lek", 377 | "classification": "mammals", 378 | "average_height": "200", 379 | "average_lifespan": "unknown", 380 | "hair_colors": "none", 381 | "skin_colors": "orange, yellow, blue, green, pink, purple, tan", 382 | "eye_colors": "blue, brown, orange, pink", 383 | "language": "Twi'leki", 384 | "homeworld_id": "37" 385 | }, 386 | { 387 | "_id": 17, 388 | "name": "Vulptereen", 389 | "classification": "unknown", 390 | "average_height": "100", 391 | "average_lifespan": "unknown", 392 | "hair_colors": "none", 393 | "skin_colors": "grey", 394 | "eye_colors": "yellow", 395 | "language": "vulpterish", 396 | "homeworld_id": "39" 397 | }, 398 | { 399 | "_id": 3, 400 | "name": "Wookiee", 401 | "classification": "mammal", 402 | "average_height": "210", 403 | "average_lifespan": "400", 404 | "hair_colors": "black, brown", 405 | "skin_colors": "gray", 406 | "eye_colors": "blue, green, yellow, brown, golden, red", 407 | "language": "Shyriiwook", 408 | "homeworld_id": "14" 409 | }, 410 | { 411 | "_id": 18, 412 | "name": "Xexto", 413 | "classification": "unknown", 414 | "average_height": "125", 415 | "average_lifespan": "unknown", 416 | "hair_colors": "none", 417 | "skin_colors": "grey, yellow, purple", 418 | "eye_colors": "black", 419 | "language": "Xextese", 420 | "homeworld_id": "40" 421 | }, 422 | { 423 | "_id": 6, 424 | "name": "Yoda's species", 425 | "classification": "mammal", 426 | "average_height": "66", 427 | "average_lifespan": "900", 428 | "hair_colors": "brown, white", 429 | "skin_colors": "green, yellow", 430 | "eye_colors": "brown, green, yellow", 431 | "language": "Galactic basic", 432 | "homeworld_id": "28" 433 | }, 434 | { 435 | "_id": 22, 436 | "name": "Zabrak", 437 | "classification": "mammal", 438 | "average_height": "180", 439 | "average_lifespan": "unknown", 440 | "hair_colors": "black", 441 | "skin_colors": "pale, brown, red, orange, yellow", 442 | "eye_colors": "brown, orange", 443 | "language": "Zabraki", 444 | "homeworld_id": "45" 445 | } 446 | ] -------------------------------------------------------------------------------- /samples/React_Sample/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "aesop-react-demo", 3 | "version": "1.0.0", 4 | "description": "", 5 | "main": "server/server.js", 6 | "scripts": { 7 | "storybook": "start-storybook" 8 | }, 9 | "author": "samanthasalley", 10 | "license": "ISC", 11 | "dependencies": { 12 | "path": "^0.12.7", 13 | "pg": "^7.12.1", 14 | "react": "^16.5.2", 15 | "redux": "^3.7.2" 16 | }, 17 | "devDependencies": { 18 | "@babel/core": "^7.1.2", 19 | "@babel/helper-module-imports": "^7.8.3", 20 | "@babel/preset-env": "^7.1.0", 21 | "@babel/preset-react": "^7.0.0", 22 | "@storybook/addon-actions": "^5.3.3", 23 | "@storybook/react": "^5.3.3", 24 | "babel-loader": "^8.0.4", 25 | "css-loader": "^1.0.1", 26 | "file-loader": "^4.0.0", 27 | "html-webpack-plugin": "^3.2.0", 28 | "morgan": "^1.9.1", 29 | "style-loader": "^0.23.1", 30 | "url-loader": "^2.0.1", 31 | "webpack": "^4.20.2", 32 | "webpack-cli": "^3.1.2", 33 | "webpack-dev-server": "^3.1.9", 34 | "webpack-hot-middleware": "^2.24.3" 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /samples/Vue_Sample/.storybook/config.js: -------------------------------------------------------------------------------- 1 | // .storybook/config.js 2 | 3 | import Vue from 'vue'; 4 | import { configure } from '@storybook/vue'; 5 | import '../src/components/index.css'; 6 | // Import your custom components. 7 | import EmployeeForm from '../src/components/EmployeeForm.vue' 8 | import EmployeeTable from '../src/components/EmployeeTable.vue' 9 | 10 | // Register custom components. 11 | Vue.component('item', EmployeeForm); 12 | Vue.component('item', EmployeeTable) 13 | 14 | 15 | function loadStories() { 16 | 17 | // You can require as many stories as you need. 18 | require('../src/components/EmployeeForm.stories') 19 | require('../src/components/EmployeeTable.stories') 20 | } 21 | 22 | configure(loadStories, module); -------------------------------------------------------------------------------- /samples/Vue_Sample/.storybook/main.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | stories: ['../src/**/*.stories.[tj]s'], 3 | }; -------------------------------------------------------------------------------- /samples/Vue_Sample/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "hello-world", 3 | "version": "0.1.0", 4 | "private": true, 5 | "scripts": { 6 | "serve": "vue-cli-service serve", 7 | "build": "vue-cli-service build", 8 | "lint": "vue-cli-service lint", 9 | "storybook": "start-storybook" 10 | }, 11 | "dependencies": { 12 | "core-js": "^3.4.4", 13 | "babel-preset-vue": "^2.0.2", 14 | "vue": "^2.6.10" 15 | }, 16 | "devDependencies": { 17 | "@storybook/vue": "^6.5.12", 18 | "@vue/cli-plugin-babel": "^4.1.0", 19 | "@vue/cli-plugin-eslint": "^4.1.0", 20 | "@vue/cli-service": "^5.0.8", 21 | "babel-eslint": "^10.0.3", 22 | "eslint": "^5.16.0", 23 | "eslint-plugin-vue": "^5.0.0", 24 | "vue-template-compiler": "^2.6.10" 25 | }, 26 | "eslintConfig": { 27 | "root": true, 28 | "env": { 29 | "node": true 30 | }, 31 | "extends": [ 32 | "plugin:vue/essential", 33 | "eslint:recommended" 34 | ], 35 | "rules": {}, 36 | "parserOptions": { 37 | "parser": "babel-eslint" 38 | } 39 | }, 40 | "browserslist": [ 41 | "> 1%", 42 | "last 2 versions" 43 | ] 44 | } 45 | -------------------------------------------------------------------------------- /samples/Vue_Sample/src/App.vue: -------------------------------------------------------------------------------- 1 | 13 | 14 | 50 | 51 | 67 | -------------------------------------------------------------------------------- /samples/Vue_Sample/src/components/EmployeeForm.js: -------------------------------------------------------------------------------- 1 | export default { 2 | name: 'EmployeeForm ', 3 | 4 | data() { 5 | return { 6 | employee: { 7 | name: 'test1', 8 | email: 'test2', 9 | }, 10 | } 11 | }, 12 | 13 | template: ` 14 |
15 |
16 | 17 | 18 | 19 | 20 | 21 |
22 |
23 | ` 24 | }; 25 | -------------------------------------------------------------------------------- /samples/Vue_Sample/src/components/EmployeeForm.stories.js: -------------------------------------------------------------------------------- 1 | // src/stories.js 2 | 3 | import EmployeeForm from './EmployeeForm' 4 | 5 | export default { 6 | title: 'Employee Form', 7 | component: EmployeeForm 8 | } 9 | 10 | export const Default_Employee_Form = () => ({ 11 | components: { EmployeeForm }, 12 | template: ` 13 |
14 |
15 | 16 | 17 | 18 | 19 | 20 |
21 |
22 | ` 23 | }); -------------------------------------------------------------------------------- /samples/Vue_Sample/src/components/EmployeeForm.vue: -------------------------------------------------------------------------------- 1 | 12 | 13 | 26 | 27 | -------------------------------------------------------------------------------- /samples/Vue_Sample/src/components/EmployeeTable.js: -------------------------------------------------------------------------------- 1 | export default { 2 | name: 'EmployeeTable ', 3 | 4 | template: ` 5 |
6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 |
Employee NameEmployee e-mail
Kenny MaPublicRelations@Aesop.com
Keith CagneyMarketing@Aesop.com
Ola AdedoyinNodeMaster@Aesop.com
Jim GaryGraphicDesigner@Aesop.com
Arlo GuiwoHumanResources@Aesop.com
Austin RubyManager@Aesop.com
40 |
41 | ` 42 | }; 43 | -------------------------------------------------------------------------------- /samples/Vue_Sample/src/components/EmployeeTable.stories.js: -------------------------------------------------------------------------------- 1 | // src/stories.js 2 | 3 | import EmployeeForm from './EmployeeForm' 4 | 5 | export default { 6 | title: 'Employee Form', 7 | component: EmployeeForm 8 | } 9 | 10 | export const Default_Employee_Table = () => ({ 11 | components: { EmployeeForm }, 12 | template: ` 13 |
14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 |
Employee NameEmployee e-mail
Kenny MaPublicRelations@Aesop.com
Keith CagneyMarketing@Aesop.com
Ola AdedoyinNodeMaster@Aesop.com
Jim GaryGraphicDesigner@Aesop.com
Arlo GuiwoHumanResources@Aesop.com
Austin RubyManager@Aesop.com
48 |
49 | ` 50 | }); -------------------------------------------------------------------------------- /samples/Vue_Sample/src/components/EmployeeTable.vue: -------------------------------------------------------------------------------- 1 | 39 | 40 | 48 | 49 | -------------------------------------------------------------------------------- /samples/Vue_Sample/src/components/HelloWorld.vue: -------------------------------------------------------------------------------- 1 | 32 | 33 | 41 | 42 | 43 | 59 | -------------------------------------------------------------------------------- /samples/Vue_Sample/src/main.js: -------------------------------------------------------------------------------- 1 | import Vue from 'vue' 2 | import App from './App.vue' 3 | 4 | Vue.config.productionTip = false 5 | 6 | new Vue({ 7 | render: h => h(App), 8 | }).$mount('#app') 9 | -------------------------------------------------------------------------------- /src/extension.ts: -------------------------------------------------------------------------------- 1 | import * as vscode from 'vscode'; 2 | import { fileURLToPath } from 'url'; 3 | import * as events from 'events'; 4 | import sbChecks from './utils/sbChecks'; 5 | import logger from './utils/logger'; 6 | import AesopViewCreator from './webview/create-webview'; 7 | import ProcessService from './processes/process.service' 8 | 9 | 10 | export function activate(context: vscode.ExtensionContext) { 11 | //define PORT and host variables to feed the webview content from SB server 12 | const fileName: string = 'extension.ts'; 13 | const aesopEmitter = new events.EventEmitter(); 14 | 15 | let currentPanel: vscode.WebviewPanel | undefined = undefined; 16 | //@TODO: if aesop already opened sb in webview - subsequent calls to aesop should not open a new webview 17 | 18 | //set context "aesop-awake" to true; enabling views 19 | vscode.commands.executeCommand("setContext", "aesop-awake", true); 20 | 21 | 22 | //create status could also be modularized or removed since we have a progress bar 23 | const statusText = vscode.window.createStatusBarItem(vscode.StatusBarAlignment.Left, 7); 24 | statusText.text = "Aesop is finding your Storybook dependency..." 25 | statusText.color = "#FFFFFF"; 26 | statusText.command = undefined; 27 | statusText.tooltip = "Aesop status"; 28 | 29 | //create disposable to register Aesop Awaken command to subscriptions 30 | let disposable: vscode.Disposable = vscode.commands.registerCommand('extension.aesopAwaken', () => { 31 | aesopEmitter.removeAllListeners(); 32 | statusText.show(); 33 | 34 | //creates progress bar during run up of webview 35 | vscode.window.withProgress({ 36 | location: vscode.ProgressLocation.Notification, 37 | title: `Running Aesop For Storybook`, 38 | cancellable: true 39 | }, (progress, token) => { 40 | //if a user hits the cancel button on the loading message, the process ends 41 | token.onCancellationRequested(() => { 42 | logger.write(`User has cancelled Aesop`, fileName, 'withProgress'); 43 | statusText.dispose(); 44 | process.exit(1); 45 | }); 46 | 47 | //for each stage of the startup, increment the progress counter 48 | 49 | aesopEmitter.once('found_dependency', () => progress.report({ message: 'Found the Storybook Dependency', increment: 10 })); 50 | aesopEmitter.once('found_nodeps', () => progress.report({ message: `Found Node Processes`, increment: 25 })); 51 | aesopEmitter.once('found_storybookps', () => progress.report({ message: `Found a Storybook Process`, increment: 40 })); 52 | aesopEmitter.once('start_storybook', () => progress.report({ message: `Starting Storybook for you`, increment: 40 })); 53 | aesopEmitter.once('create_webview', () => progress.report({ message: `Creating Webview`, increment: 25 })); 54 | 55 | //once the returned promise resolves, the loading message disappears 56 | var p = new Promise(resolve => { 57 | return aesopEmitter.once('create_webview', () => resolve()); 58 | }); 59 | 60 | return p; 61 | }) 62 | 63 | 64 | 65 | //define a path to the user's root working directory 66 | const rootDir: string = fileURLToPath(vscode.workspace.workspaceFolders[0].uri.toString(true)); 67 | 68 | //manual dependency injection 69 | //declare core vscode functionality to be injected into services 70 | const vscodeDepPack = { 71 | vscode, 72 | rootDir, 73 | statusText, 74 | currentPanel, 75 | aesopEmitter, 76 | context 77 | } 78 | 79 | //each service deconstructs what it needs and stores the references in the constructor 80 | //maybe rename sbChecker to validatorService 81 | const sbChecker = new sbChecks(vscodeDepPack); 82 | const processService = new ProcessService(vscodeDepPack); 83 | const viewCreator = new AesopViewCreator(vscodeDepPack); 84 | 85 | //event listeners used to keep track of function order 86 | const errorHandler = (error) => { 87 | vscode.window.showErrorMessage(`Something went wrong!`) 88 | statusText.dispose(); 89 | logger.write(error, fileName, 'errorHandler'); 90 | process.exit() 91 | } 92 | 93 | //probably should wrap the creation of these event handlers in a function and store on a different file 94 | 95 | aesopEmitter.on('error', errorHandler) 96 | process.on('unhandledRejection', errorHandler) 97 | 98 | aesopEmitter.once('found_dependency', sbChecker.nodeProc); 99 | aesopEmitter.once('found_nodeps', sbChecker.storyBookProc); 100 | aesopEmitter.once('found_storybookps', processService.findLocation); 101 | aesopEmitter.once('start_storybook', processService.startStorybook); 102 | aesopEmitter.once('create_webview', viewCreator.createAesop); 103 | 104 | //kickstart process 105 | sbChecker.dependency(); 106 | 107 | }); //close disposable 108 | 109 | context.subscriptions.push(disposable); 110 | } 111 | 112 | 113 | export function deactivate() { 114 | process.exit(); 115 | } 116 | -------------------------------------------------------------------------------- /src/processes/commands.ts: -------------------------------------------------------------------------------- 1 | import * as os from 'os'; 2 | 3 | const netStatCommandLibrary = { 4 | linux: { 5 | cmd: 'netstat', 6 | args: ['-apntu'], 7 | }, 8 | darwin: { 9 | cmd: 'netstat', 10 | args: ['-a', '-v', '-n', '-p', 'tcp'], 11 | }, 12 | win32: { 13 | cmd: 'netstat.exe', 14 | args: ['-a', '-n', '-o'], 15 | }, 16 | }; 17 | 18 | const searchCommandLibrary = { 19 | linux: { 20 | cmd: "grep" 21 | }, 22 | darwin: { 23 | cmd: "grep" 24 | }, 25 | win32: { 26 | cmd: "FINDSTR" 27 | } 28 | } 29 | 30 | 31 | const platform: NodeJS.Platform = os.platform(); 32 | const netstatCommand = netStatCommandLibrary[platform]; 33 | const searchCommand = searchCommandLibrary[platform]; 34 | export default { 35 | netstatCommand, searchCommand, platform 36 | } -------------------------------------------------------------------------------- /src/processes/process.service.ts: -------------------------------------------------------------------------------- 1 | import * as child_process from "child_process"; 2 | import * as fs from "fs"; 3 | import * as path from "path"; 4 | import commands from "./commands"; 5 | import logger from "../utils/logger"; 6 | 7 | const { netstatCommand, searchCommand, platform } = commands; 8 | 9 | class ProcessService { 10 | public port: number; 11 | private rootDir: string; 12 | private fileName: string; 13 | private vscode; 14 | private statusText; 15 | private aesopEmitter; 16 | constructor({ rootDir, vscode, statusText, aesopEmitter }) { 17 | this.rootDir = rootDir; 18 | this.vscode = vscode; 19 | this.statusText = statusText; 20 | this.aesopEmitter = aesopEmitter; 21 | this.fileName = "@process.service.ts"; 22 | this.startStorybook = this.startStorybook.bind(this); 23 | this.findLocation = this.findLocation.bind(this); 24 | this.locationViaNetStat = this.locationViaNetStat.bind(this); 25 | } 26 | 27 | //make location checks private methods that are referred to in a findLocation check 28 | 29 | public findLocation(pid) { 30 | logger.write( 31 | "Attempting to find Storybook Location", 32 | this.fileName, 33 | "findLocation" 34 | ); 35 | const processPid = parseInt(pid).toString(); 36 | this.locationViaNetStat(processPid); 37 | } 38 | 39 | //test 40 | private locationViaNetStat(processPid) { 41 | logger.write( 42 | "Attempting to locate via Netstat", 43 | this.fileName, 44 | "locationViaNetstat" 45 | ); 46 | 47 | const netStatProcess = child_process.spawnSync( 48 | netstatCommand.cmd, 49 | netstatCommand.args 50 | ); 51 | const grepProcess = child_process.spawnSync( 52 | searchCommand.cmd, 53 | [processPid], 54 | { input: netStatProcess.stdout, encoding: "utf-8" } 55 | ); 56 | 57 | const data = grepProcess.stdout; 58 | 59 | const parts = data.split(/\s/).filter(String); 60 | 61 | const partIndex = (platform === 'win32') ? 1 : 3; 62 | const localAddress = parts[partIndex] 63 | 64 | let portStr = '' 65 | const nanRegex = new RegExp('[^0-9]') 66 | 67 | for (let i = localAddress.length - 1; i >= 0; i--) { 68 | if (nanRegex.test(localAddress[i])) break; 69 | portStr = localAddress[i] + portStr; 70 | } 71 | 72 | this.port = parseInt(portStr); 73 | this.aesopEmitter.emit('create_webview', this.port); 74 | 75 | logger.write( 76 | `Found Storybook location via Netstat`, 77 | this.fileName, 78 | "locationViaNetstat/grepProcess" 79 | ); 80 | } 81 | 82 | //MAYBE separate this function? 83 | //possibly break it down as well into: 84 | //grab json script 85 | //start storybook 86 | 87 | startStorybook() { 88 | let data: Buffer; 89 | logger.write( 90 | "Starting Storybook for you!", 91 | this.fileName, 92 | "startStorybook" 93 | ); 94 | 95 | try { 96 | data = fs.readFileSync(path.join(this.rootDir, "package.json")); 97 | logger.write( 98 | "Obtained data from package.json", 99 | this.fileName, 100 | "startStorybook" 101 | ); 102 | } catch (err) { 103 | this.vscode.window.showErrorMessage( 104 | `Aesop is attempting to read ${this.rootDir}. Is there a package.json file here?` 105 | ); 106 | this.statusText.dispose(); 107 | return false; 108 | } 109 | 110 | this.statusText.text = `Checking package.json...`; 111 | 112 | //check if the user has custom configurations for starting storybook 113 | 114 | let packageJSON = JSON.parse(data.toString()); 115 | let storybookScript = packageJSON.scripts.storybook; 116 | let retrievedScriptArray = storybookScript.split(" "); 117 | 118 | //older Windows systems support here: check platform, change process command accordingly 119 | 120 | const sbCLI = "./node_modules/.bin/start-storybook"; 121 | const sbStartIndex = retrievedScriptArray.indexOf("start-storybook"); 122 | retrievedScriptArray[sbStartIndex] = sbCLI; 123 | retrievedScriptArray.push("--ci"); 124 | 125 | //launch storybook using a child process 126 | const childProcessArguments = 127 | platform === "win32" ? ["run", "storybook"] : retrievedScriptArray; 128 | const childProcessCommand = platform === "win32" ? "npm.cmd" : "node"; 129 | 130 | const runSb = child_process.spawn( 131 | childProcessCommand, 132 | childProcessArguments, 133 | { 134 | cwd: this.rootDir, 135 | env: process.env, 136 | windowsHide: false, 137 | windowsVerbatimArguments: true, 138 | } 139 | ); 140 | 141 | this.statusText.text = `Done looking. Aesop will now launch Storybook in the background.`; 142 | 143 | runSb.stdout.setEncoding("utf8"); 144 | 145 | let counter = 0; 146 | 147 | //Storybook outputs three messages to the terminal as it spins up 148 | //grab the port from the last message to listen in on the process 149 | 150 | let callback = (data) => { 151 | let str = data.toString().split(" "); 152 | counter += 1; 153 | logger.write( 154 | `This is data: ${data.toString()}`, 155 | this.fileName, 156 | "startStorybook/runSb" 157 | ); 158 | 159 | if (counter >= 2) { 160 | for (let i = 165; i < str.length; i += 1) { 161 | if (str[i].includes("localhost")) { 162 | const path = str[i]; 163 | const regExp = /[^0-9]/g; 164 | this.port = path.replace(regExp, ""); 165 | 166 | logger.write( 167 | "Found instance in stdout that includes localhost", 168 | this.fileName, 169 | "startStorybook/runSb" 170 | ); 171 | this.aesopEmitter.emit("create_webview", this.port); 172 | return true; 173 | } 174 | } 175 | } 176 | }; 177 | callback = callback.bind(this); 178 | 179 | runSb.stdout.on("data", callback); 180 | 181 | runSb.stderr.on("data", (data) => { 182 | console.error(`stderr: ${data}`); 183 | logger.write( 184 | `This is stderr: ${data.toString()}`, 185 | this.fileName, 186 | "startStorybook/runSb" 187 | ); 188 | // process.exit(1); 189 | }); 190 | 191 | //make sure the child process is terminated on process exit 192 | runSb.on("close", (code) => { 193 | console.log(`child process exited with code ${code}`); 194 | }); 195 | } 196 | } 197 | 198 | export default ProcessService; 199 | -------------------------------------------------------------------------------- /src/test/runTest.ts: -------------------------------------------------------------------------------- 1 | import * as path from 'path'; 2 | 3 | import { runTests } from 'vscode-test'; 4 | 5 | async function main() { 6 | try { 7 | // The folder containing the Extension Manifest package.json 8 | // Passed to `--extensionDevelopmentPath` 9 | const extensionDevelopmentPath = path.resolve(__dirname, '../../'); 10 | 11 | // The path to test runner 12 | // Passed to --extensionTestsPath 13 | const extensionTestsPath = path.resolve(__dirname, './suite/index'); 14 | 15 | // Download VS Code, unzip it and run the integration test 16 | await runTests({ extensionDevelopmentPath, extensionTestsPath }); 17 | } catch (err) { 18 | console.error('Failed to run tests'); 19 | process.exit(1); 20 | } 21 | } 22 | 23 | main(); 24 | -------------------------------------------------------------------------------- /src/test/suite/extension.test.ts: -------------------------------------------------------------------------------- 1 | import * as assert from 'assert'; 2 | 3 | // You can import and use all API from the 'vscode' module 4 | // as well as import your extension to test it 5 | import * as vscode from 'vscode'; 6 | // import * as myExtension from '../extension'; 7 | 8 | suite('Extension Test Suite', () => { 9 | vscode.window.showInformationMessage('Start all tests.'); 10 | 11 | test('Sample test', () => { 12 | assert.equal(-1, [1, 2, 3].indexOf(5)); 13 | assert.equal(-1, [1, 2, 3].indexOf(0)); 14 | }); 15 | }); 16 | 17 | //we should build this out. 18 | -------------------------------------------------------------------------------- /src/test/suite/index.ts: -------------------------------------------------------------------------------- 1 | import * as path from 'path'; 2 | import * as Mocha from 'mocha'; 3 | import * as glob from 'glob'; 4 | 5 | export function run(): Promise { 6 | // Create the mocha test 7 | const mocha = new Mocha({ 8 | ui: 'tdd', 9 | }); 10 | mocha.useColors(true); 11 | 12 | const testsRoot = path.resolve(__dirname, '..'); 13 | 14 | return new Promise((c, e) => { 15 | glob('**/**.test.js', { cwd: testsRoot }, (err, files) => { 16 | if (err) { 17 | return e(err); 18 | } 19 | 20 | // Add files to the test suite 21 | files.forEach(f => mocha.addFile(path.resolve(testsRoot, f))); 22 | 23 | try { 24 | // Run the mocha test 25 | mocha.run(failures => { 26 | if (failures > 0) { 27 | e(new Error(`${failures} tests failed.`)); 28 | } else { 29 | c(); 30 | } 31 | }); 32 | } catch (err) { 33 | e(err); 34 | } 35 | }); 36 | }); 37 | } 38 | -------------------------------------------------------------------------------- /src/utils/logger.ts: -------------------------------------------------------------------------------- 1 | import * as fs from "fs"; 2 | import * as path from 'path'; 3 | import { performance } from 'perf_hooks'; 4 | 5 | class Logger { 6 | private writeStream; 7 | 8 | open(rootDir: string): void { 9 | this.writeStream = fs.createWriteStream(path.join(rootDir, `AesopLogs.txt`)); 10 | this.writeStream.on('error', (err) => { 11 | throw new Error(err); 12 | }) 13 | } 14 | 15 | write(data: string, fileName: string, functionName: string): void { 16 | this.writeStream.write(`[${performance.now()}] ${fileName} / ${functionName}():\n` + data + '\n'); 17 | } 18 | 19 | end(): void { 20 | this.writeStream.end(); 21 | } 22 | 23 | } 24 | 25 | 26 | export default new Logger(); 27 | -------------------------------------------------------------------------------- /src/utils/sbChecks.ts: -------------------------------------------------------------------------------- 1 | import * as fs from "fs"; 2 | import * as path from 'path'; 3 | import logger from './logger' 4 | import * as util from 'util'; 5 | import * as ps from 'ps-node'; 6 | 7 | 8 | class StorybookChecker { 9 | rootDir: string; 10 | vscode: any; 11 | aesopEmitter: any; 12 | private fileName : string; 13 | constructor({ rootDir, vscode, aesopEmitter }) { 14 | this.rootDir = rootDir; 15 | this.vscode = vscode; 16 | this.aesopEmitter = aesopEmitter; 17 | logger.open(rootDir); 18 | this.fileName = 'sbChecks.ts' 19 | this.nodeProc = this.nodeProc.bind(this); 20 | this.storyBookProc = this.storyBookProc.bind(this); 21 | } 22 | //check if Storybook is a dependency 23 | dependency(): void { 24 | 25 | try { 26 | fs.accessSync(path.join(this.rootDir, '/node_modules/@storybook')); 27 | logger.write('Aesop has found a Storybook dependency', this.fileName, 'dependency'); 28 | this.aesopEmitter.emit('found_dependency') 29 | 30 | } catch (error) { 31 | logger.write('Error finding storybook dependency', this.fileName,'dependency'); 32 | this.vscode.window.showErrorMessage(`Aesop could not find Storybook as a dependency in the active folder, ${this.rootDir}`); 33 | throw new Error('Error finding a storybook project'); 34 | } 35 | } 36 | 37 | 38 | //should I separate the nodeProc checks into the process service? 39 | //if I do, I can decouple vscode from this class and turn it into a function instead 40 | 41 | //this is where I'm currently getting errors. 42 | 43 | nodeProc() { 44 | // const psLookup = util.promisify(ps.lookup); 45 | logger.write('Looking for node processes!', this.fileName, 'nodeProc') 46 | let callback = (err, resultList) => { 47 | if (err) return this.aesopEmitter('error', err); 48 | logger.write(`Found node processes!`, this.fileName, 'nodeProc'); 49 | this.aesopEmitter.emit('found_nodeps', resultList) 50 | } 51 | callback = callback.bind(this); 52 | 53 | ps.lookup({ command: 'node', psargs: 'ux' }, callback); 54 | 55 | 56 | } 57 | 58 | //can definitely optimize 59 | storyBookProc(resultList: []): void { 60 | logger.write('Looking for Storybook Process!', this.fileName, 'storyBookProc') 61 | let process: string; 62 | for (let i = 0; i < resultList.length; i++) { 63 | process = resultList[i]['arguments'][0]; 64 | //OPTIMIZE THIS 65 | if (process.includes('node_modules') && process.includes('storybook')) { 66 | const { pid } = resultList[i] 67 | logger.write(`Found the Storybook Process at PID ${pid}`, this.fileName, 'storyBookProc') 68 | return this.aesopEmitter.emit('found_storybookps', pid) 69 | 70 | } 71 | } 72 | logger.write('Could not find Storybook Proc!', this.fileName, 'storyBookProc'); 73 | 74 | return this.aesopEmitter.emit('start_storybook'); 75 | } 76 | } 77 | 78 | export default StorybookChecker; -------------------------------------------------------------------------------- /src/webview/create-webview.ts: -------------------------------------------------------------------------------- 1 | import logger from '../utils/logger'; 2 | 3 | class AesopViewCreator { 4 | private fileName: string; 5 | private vscode; 6 | private statusText; 7 | private currentPanel; 8 | private context; 9 | constructor({ vscode, context, statusText, currentPanel }) { 10 | this.vscode = vscode; 11 | this.context = context; 12 | this.statusText = statusText; 13 | this.currentPanel = currentPanel; 14 | this.fileName = 'create-webview.ts' 15 | this.createAesop = this.createAesop.bind(this); 16 | } 17 | 18 | 19 | createAesop(port: number, host: string = 'localhost'): void { 20 | logger.write(`Attempting to create webview`, this.fileName, 'createAesop') 21 | //currentPanel stores our webview. If createAesop is called with an active webview open, display an error message. If not, create a new panel and reassign global variable. 22 | if (this.currentPanel) { 23 | this.vscode.window.showErrorMessage(`Aesop has already been run.`); 24 | return; 25 | } 26 | 27 | this.statusText.hide(); 28 | this.vscode.window.showInformationMessage(`Welcome to Aesop Storybook`); 29 | this.currentPanel = this.vscode.window.createWebviewPanel( 30 | 'aesop-sb', 31 | 'Aesop', 32 | this.vscode.ViewColumn.Beside, 33 | { 34 | enableCommandUris: true, 35 | enableScripts: true, 36 | portMapping: [{ 37 | webviewPort: port, 38 | extensionHostPort: port 39 | }], 40 | localResourceRoots: [this.vscode.Uri.file(this.context.extensionPath)], 41 | } 42 | ); 43 | 44 | this.currentPanel.webview.html = ` 45 | 46 | 47 | 48 | 49 | 50 | Aesop 51 | 55 | 56 | 57 | 58 | 59 | ` 60 | 61 | this.currentPanel.onDidDispose(() => { 62 | this.currentPanel = undefined; 63 | }, null, this.context.subscriptions); 64 | 65 | 66 | } 67 | } // close createAesop helper function 68 | 69 | export default AesopViewCreator; -------------------------------------------------------------------------------- /tsconfig.json: -------------------------------------------------------------------------------- 1 | { "compilerOptions": { 2 | "module": "commonjs", 3 | "target": "es6", 4 | "outDir": "out", 5 | "lib": [ 6 | "es6", 7 | "DOM", 8 | "DOM.Iterable" 9 | ], 10 | "sourceMap": true, 11 | "rootDir": "src", 12 | "strict": false /* enable all strict type-checking options */ 13 | /* Additional Checks */ 14 | // "noImplicitReturns": true, /* Report error when not all code paths in function return a value. */ 15 | // "noFallthroughCasesInSwitch": true, /* Report errors for fallthrough cases in switch statement. */ 16 | // "noUnusedParameters": true, /* Report errors on unused parameters. */ 17 | }, 18 | "exclude": [ 19 | "node_modules", 20 | ".vscode-test" 21 | ] 22 | } 23 | -------------------------------------------------------------------------------- /webpack.config.js: -------------------------------------------------------------------------------- 1 | //@ts-check 2 | 3 | 'use strict'; 4 | 5 | const path = require('path'); 6 | 7 | /**@type {import('webpack').Configuration}*/ 8 | const config = { 9 | target: 'node', 10 | entry: './src/extension.ts', 11 | output: { 12 | path: path.resolve(__dirname, 'dist'), 13 | filename: 'extension.js', 14 | libraryTarget: 'commonjs2', 15 | devtoolModuleFilenameTemplate: '../[resource-path]' 16 | }, 17 | devtool: 'source-map', 18 | externals: { 19 | vscode: 'commonjs vscode' 20 | }, 21 | resolve: { 22 | extensions: ['.ts', '.js'] 23 | }, 24 | module: { 25 | rules: [ 26 | { 27 | test: /\.ts$/, 28 | exclude: /node_modules/, 29 | use: [ 30 | { 31 | loader: 'ts-loader' 32 | } 33 | ] 34 | } 35 | ] 36 | } 37 | }; 38 | 39 | module.exports = config; --------------------------------------------------------------------------------