├── .gitignore ├── CHANGELOG.md ├── LICENSE.md ├── README.md ├── assets ├── capture.png ├── meteor_logo.svg └── settings.png ├── keymaps └── meteor-helper.cson ├── lib ├── meteor-helper-view.coffee └── meteor-helper.coffee ├── menus └── meteor-helper.cson ├── package.json ├── spec ├── meteor-helper-spec.coffee └── meteor-helper-view-spec.coffee └── styles └── meteor-helper.less /.gitignore: -------------------------------------------------------------------------------- 1 | .DS_Store 2 | npm-debug.log 3 | node_modules 4 | .meteor 5 | -------------------------------------------------------------------------------- /CHANGELOG.md: -------------------------------------------------------------------------------- 1 | ## 0.29.0 - Fix for strict mode 2 | * Fix for Atom 1.12.X as strict mode has been activated 3 | 4 | ## 0.28.0 5 | * Clearer `menu.cson`. 6 | * Ability to set the NODE_ENV in settings or mup.json: Thank goes to [Jaco Swarts](https://github.com/productiveme) :clap:. 7 | 8 | ## 0.26.0/0.27.0 - CSS & OPLOG_URL 9 | * Force a `top: 0` to `panel-body`: #45. 10 | From @jazee 👏 11 | * Setting for `OPLOG_URL` was defined but not used: #49. 12 | * Package bumped. 13 | 14 | ## 0.25.0 - Meteor settings 15 | From @coopermaruyama 👏 16 | * Add field to settings panel to specify path to settings.json file. 17 | * Uses absolute or relative path. 18 | * Ensures the file exists before launching. 19 | 20 | ## 0.24.3 - Speeds up initialization 21 | * #36 22 | 23 | ## 0.24.2 - Deprecation fixes 24 | * `getPath` deprecation. 25 | 26 | ## 0.24.1 - Deprecation fixes 27 | * Menu deprecation: Contributions from: @zimme and @nyaaao :clap: 28 | 29 | ## 0.24.0 - Multiple paths 30 | * Better setting description from @johnschult and @nowakstefan. 31 | * Multiple paths from @johnschult and @nowakstefan. 32 | * FAQs in the README. 33 | 34 | ## 0.23.0 - Automatic activation 35 | * Rely on automatic activation for Settings issues #32 36 | 37 | ## 0.22.0 - Atom's View 38 | * Using SpacePen package for Settings issues #32 39 | 40 | ## 0.21.1 - Styles location deprecation warning 41 | * Move stylesheets to styles #31 by @zimme :clap: 42 | * Package bumped. 43 | 44 | ## 0.21.0 - Show or hide Meteor's pane 45 | * Add a shortcut for showing or hiding Meteor's pane, thus avoiding mouse use. 46 | 47 | ## 0.20.1 - Visual fixes & Optimized Meteor logo 48 | * Small CSS fixes :lipstick: 49 | * 50% optimization on Meteor's logo. 50 | 51 | ## 0.20.0 - Fix workspace's view deprecation 52 | * atom.workspaceView is no longer available (#26). 53 | 54 | ## 0.19.0 - Octicon fonts, deprecation warnings, OS specific shortcuts 55 | * Deprecation warning fixes and OS specific shortcuts by @nyaaao :clap: 56 | * Octicon icons instead of font-awesome. 57 | * Updates of Velocity. 58 | 59 | ## 0.18.1 - Panel fixes 60 | * Autoscroll fixes by @nyaaao :clap: 61 | * Panel header size fixes :lipstick: 62 | 63 | ## 0.18.0 - Reset Meteor 64 | * Use `ctrl-alt-r` for resetting your Meteor instance. 65 | 66 | ## 0.16.0 - Customized log colors 67 | * Display Meteor's log using currently selected Atom theme. 68 | * Remove date from logs for better readability (only conserving time). 69 | 70 | ## 0.15.0 - New Meteor logo 71 | * Pure :lipstick:, but so nice. Logo is from [Ben Strahan](https://twitter.com/benjaminstrahan) :clap: 72 | 73 | ## 0.14.1 - Better exit support 74 | * Now relying on window's events for killing Meteor process. 75 | 76 | ## 0.14.0 - Support for MONGO_OPLOG_URL 77 | * Remove unnecessary actions in menu. 78 | * Adding support for MONGO_OPLOG_URL. 79 | * Some additional documentation. 80 | 81 | ## 0.13.1 - Compatibility with Atom-0.138-0 82 | * Better isolation of Velocity. 83 | * Removing q-io as it messes with the Node's module cache feature introduced in Atom-0.138.0. 84 | 85 | ## 0.13.0 - Per project configuration & debug 86 | * Use the Meteor-0.9.4 debug capability: `meteor debug`. 87 | * Per project configuration uses [Meteor Up](https://github.com/arunoda/meteor-up)'s configuration file. 88 | 89 | ## 0.12.0 - Adaptation to new configuration scheme 90 | * Adapt to Atom changes on the configuration scheme: [Config API Improvements](http://blog.atom.io/2014/10/02/config-api-has-schema.html). 91 | 92 | ## 0.11.0 - Stack trace & console.log/error readability 93 | * Use ansi-to-html to add new lines. Thank goes to [Joshua Horovitz](https://github.com/joshuahhh) for #10 :clap:. 94 | * Report Meteor's `console.error` as errors. Thus firing up the error's pane. 95 | * Keep previous status pane when Meteor is only reporting `console.log`. 96 | * Split Meteor's output when Meteor's console are not flushed (multiple console logs received on `stdout`). 97 | 98 | ## 0.10.0 - Theming Meteor's console.log 99 | * Customize your `console.log`'s color in the settings' (requested by [Andreas Fruth](http://crater.io/posts/W2Az8PQJ4aKTuf2ET)):lipstick:. 100 | 101 | ## 0.9.0 - Debug Meteor and custom MongoDB URL 102 | * Launch Meteor in debug mode. 103 | * Customize MongoDB's URL (see enhancement request #7). 104 | * Dependencies update: 105 | * font-awesome: 4.1 to 4.2 106 | * velocity-animate: 0.4.1 to 1.0.0 107 | 108 | ## 0.8.1 - Default for Meteor 109 | * As Meteorite is not anymore required, Meteor is set as the default :zap:. 110 | 111 | ## 0.8.0 - Better theming 112 | * Better light and dark theme integration :lipstick:. Thank goes to [Bernardo Kuri](https://github.com/bkuri) :clap:. 113 | * Fix fonts setting on Linux :penguin:. Thank goes to [Bernardo Kuri](https://github.com/bkuri) :clap:. 114 | 115 | ## 0.7.0 - Production checks 116 | * Setting for adding the production flag :factory: 117 | 118 | ## 0.6.0 - Kill process on exit 119 | * Small refactoring :cyclone: 120 | * Kill Meteor's process and subprocess (Mongo): Fix issue #3 :boom: 121 | 122 | ## 0.5.0 - Change port setting 123 | * Change the port on which Meteor is listening :ear: 124 | 125 | ## 0.4.1 - Meteorite quick fix for Atom call outside a terminal 126 | * A simple fix that should work for OSX :apple: and Linux :penguin: (Meteorite isn't available on Windows) 127 | 128 | ## 0.4.0 - Published Release 129 | * Removal of Bower dependencies 130 | 131 | ## 0.1.0 - Initial Release 132 | * Simple process exec for launching Meteor :black_circle: 133 | -------------------------------------------------------------------------------- /LICENSE.md: -------------------------------------------------------------------------------- 1 | Copyright (c) 2014 [Pierre-Eric Marchandet](https://github.com/PEM--) 2 | 3 | Permission is hereby granted, free of charge, to any person obtaining 4 | a copy of this software and associated documentation files (the 5 | "Software"), to deal in the Software without restriction, including 6 | without limitation the rights to use, copy, modify, merge, publish, 7 | distribute, sublicense, and/or sell copies of the Software, and to 8 | permit persons to whom the Software is furnished to do so, subject to 9 | the following conditions: 10 | 11 | The above copyright notice and this permission notice shall be 12 | included in all copies or substantial portions of the Software. 13 | 14 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 15 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 16 | MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 17 | NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE 18 | LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION 19 | OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION 20 | WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 21 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Meteor-helper: Call Meteor from Atom.io 2 | 3 | ## Introduction 4 | :rocket: Launch [Meteor](https://www.meteor.com/) 5 | and [Meteorite](https://atmospherejs.com/) inside [Atom.io](https://atom.io/) 6 | 7 | ![Meteor.js from Atom.io](https://raw.githubusercontent.com/PEM--/meteor-helper/master/assets/capture.png) 8 | 9 | ## Installation 10 | Either use [Atom.io](https://atom.io/) inner packaging tool or the following 11 | command line: 12 | ```bash 13 | apm install meteor-helper 14 | ``` 15 | 16 | ## Settings 17 | With this package, you can: 18 | * Launch or kill Meteor using: 19 | * On Linux and Windows: **CTRL**+**ALT**+**m** 20 | * On OSX: **CMD**+**ALT**+**m** 21 | * Reset Meteor using: 22 | * On Linux and Windows: **CTRL**+**ALT**+**r** 23 | * On OSX: **CMD**+**ALT**+**r** 24 | * Show/hide Meteor's panel: 25 | * On Linux and Windows: **CTRL**+**ALT**+**h** 26 | * On OSX: **CMD**+**ALT**+**h** 27 | * Watch the Meteor's CLI information in a dedicated pane. 28 | * See Meteor's status in a dedicated status bar. 29 | * When Meteor's status goes wrong, the pane automatically shows up and displays 30 | the last CLI information. 31 | 32 | In the settings, you can customize this package behavior: 33 | * Meteor application path. The default is: `.`. 34 | * Command and its path. The default is: `/usr/local/bin/meteor`. 35 | * Main listening port. The default is 3000. 36 | * Production flag. The default is `false`. 37 | * Debug flag. The default is `false`. 38 | * MongoDB's URL. Leave it empty to use the default embedded MongoDB in Meteor. 39 | * MongoDB's Oplog URL. Leave it empty to use the default embedded MongoDB in Meteor. 40 | * NODE_ENV environment variable. The default is `undefined`. 41 | 42 | ![Settings](https://raw.githubusercontent.com/PEM--/meteor-helper/master/assets/settings.png) 43 | 44 | You can overwrite variable settings with a per project file named `mup.json` at 45 | the root of your project using [Meteor Up](https://github.com/arunoda/meteor-up) 46 | recommendations. The following variables supersede the settings ones: 47 | * `env.PORT`: Meteor's port. 48 | * `env.MONGO_URL`: MongoDB's URL. 49 | * `env.MONGO_OPLOG_URL`: MongoDB's Oplog URL. 50 | * `env.NODE_ENV`: The NODE_ENV environment variable. 51 | * `app`: Meteor's application path. 52 | 53 | > **Tips**: To create a default Meteor Up project, simply use the following 54 | > commands: 55 | > ```bash 56 | > npm install -g mup 57 | > mup init 58 | > ``` 59 | > And removes the unnecessary comments and add the following environment 60 | > variables with your own values: 61 | > ```json 62 | > "env": { 63 | > "PORT": 3002, 64 | > "MONGO_URL": "mongodb://LOGIN:PASSWORD@ACCOUNT.mongohq.com:10023/MyApp", 65 | > }, 66 | > ``` 67 | 68 | ## Misc 69 | * More informations on my blog site :eyeglasses: : [Meteor.js from within Atom.io](http://pem-musing.blogspot.com/2014/07/meteorjs-from-within-atomio-full-stack.html) 70 | * Declare your bugs :bug: or enhancements :sunny: on 71 | [Github](https://github.com/PEM--/meteor-helper/issues?state=open) :octocat: 72 | 73 | ## FAQ 74 | ### How to customize log colors? 75 | Atom allows you to overwrite its style in a specific file named 76 | `~/.atom/styles.less` (more info [here](https://atom.io/docs/v0.61.0/customizing-atom)). 77 | 78 | For instance: **`~/.atom/styles.less`** 79 | ```less 80 | .meteor-helper .panel-body p { 81 | font-size: 14px; 82 | color: red; 83 | } 84 | ``` 85 | ### How to launch Meteor on Windows with an appropriate PATH? 86 | There are currently 2 solutions provided by Windows users (see #36). Results 87 | seem to rely on the version of your OS. 88 | #### The simple method shared by @JohnAReid 89 | In the settings of this plugin, just add the following: 90 | `C:\Users\userFolder\AppData\Local\.meteor\meteor.bat` 91 | where `userFolder` is your short Windows's user name. 92 | #### A more advanced shared by @dtrimsd 93 | When using `C:\Users\userFolder\AppData\Local\.meteor\meteor.bat`, `SETLOCAL` 94 | to set meteor variables, the Windows command shell is pulling the normal `SET` 95 | variables including `PATH` which is required to point to the `system32` folder 96 | for `tasklist.exe`. 97 | 98 | Following the next steps should circumvent the issue: 99 | 100 | 0. Duplicate the `meteor.bat` file - call the new copy `atommeteor.bat`. 101 | 0. Open a command prompt, type `SET`, then hit **ENTER**. Copy the `PATH` variable 102 | and paste it into the new `atommetor.bat` file, just under the `SETLOCAL` 103 | line. Instead of `PATH=`, put `SET PATH=` and remember to fix the line 104 | wrapping. Windows likes to line return a lot. 105 | 0. Create a launcher in the folder for your project - call it `launcher.cmd`. 106 | This file has one line: `C:\Users\userFolder\AppData\Local\.meteor\atommeteor.bat` 107 | 108 | Removing any of these steps seems to break dependencies. 109 | 110 | ### Is there a tutorial on using Meteor with Atom? 111 | Yes, there is: https://www.youtube.com/watch?t=101&v=QSg3mKjhiws 112 | 113 | ### Settings of the package doesn't show up 114 | The package needs to be activated for modifying your settings. Just toggle 115 | Meteor and you should be fine. 116 | 117 | ### I can't load my settings.json file when Meteor is launched 118 | If you've used a relative path to your Meteor project don't forget to 119 | apply the same path modifier to the path of your settings. 120 | -------------------------------------------------------------------------------- /assets/capture.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PEM--/meteor-helper/8ec789d20511b80c8d3d740cf8279d530277bfd9/assets/capture.png -------------------------------------------------------------------------------- /assets/meteor_logo.svg: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /assets/settings.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PEM--/meteor-helper/8ec789d20511b80c8d3d740cf8279d530277bfd9/assets/settings.png -------------------------------------------------------------------------------- /keymaps/meteor-helper.cson: -------------------------------------------------------------------------------- 1 | '.platform-win32 atom-workspace, .platform-linux atom-workspace': 2 | 'ctrl-alt-m': 'meteor-helper:toggle' 3 | 'ctrl-alt-r': 'meteor-helper:reset' 4 | 'ctrl-alt-s': 'meteor-helper:showHide' 5 | 6 | '.platform-darwin atom-workspace': 7 | 'cmd-alt-m': 'meteor-helper:toggle' 8 | 'cmd-alt-r': 'meteor-helper:reset' 9 | 'cmd-alt-s': 'meteor-helper:showHide' 10 | -------------------------------------------------------------------------------- /lib/meteor-helper-view.coffee: -------------------------------------------------------------------------------- 1 | {View, $} = require 'atom-space-pen-views' 2 | {BufferedProcess} = require 'atom' 3 | fs = require 'fs' 4 | path = require 'path' 5 | velocity = require 'velocity-animate/velocity' 6 | 7 | PANE_TITLE_HEIGHT_CLOSE = 26 8 | PANE_TITLE_HEIGHT_OPEN = 150 9 | 10 | module.exports = 11 | 12 | # Public: Main Meteor's view that extends the View prototype. 13 | class MeteorHelperView extends View 14 | 15 | # Meteor's process 16 | @process: null 17 | 18 | # Public: Build the pane 19 | # 20 | # Returns: main's pane widget 21 | @content: -> 22 | @div click: 'onClick', class: 'meteor-helper 23 | tool-panel panel-bottom text-smaller', => 24 | @div class: 'panel-heading status-bar tool-panel', => 25 | @div class: 'status-bar-left pull-left meteor-logo' 26 | @div outlet: 'meteorStatus', class: 'status-bar-right pull-right', => 27 | @span class: 'loading loading-spinner-tiny inline-block' 28 | @div class: 'panel-body', => 29 | @div outlet: 'meteorDetails', class: 'meteor-details' 30 | 31 | # Public: Initialize the current package 32 | # 33 | # serializeState - The [description] as {[type]}. 34 | # 35 | # Returns: `undefined` 36 | initialize: (serializeState) -> 37 | # Import Velocity into the main window's context 38 | @velocity = velocity.bind @ 39 | # Pane is closed by default 40 | @isPaneOpened = false 41 | # Current pane status 42 | @paneIconStatus = null 43 | # Register toggle and reset 44 | atom.commands.add 'atom-workspace', 45 | 'meteor-helper:reset': => @reset() 46 | 'meteor-helper:toggle': => @toggle() 47 | 'meteor-helper:showHide': => @showHide() 48 | # Ensure destruction of Meteor's process 49 | $(window).on 'beforeunload', => @_killMeteor() 50 | 51 | # Public: Returns an object that can be retrieved when package is activated 52 | # 53 | # Returns: `undefined` 54 | serialize: -> 55 | 56 | # Public: On click, make the pane appearing or disappearing. 57 | # 58 | # evt - The event as EventType. 59 | # 60 | # Returns: `undefined` 61 | onClick: (evt) => @showHide() 62 | 63 | # Public: Make the pane appearing or disappearing. 64 | # 65 | # Returns: `undefined` 66 | showHide: => 67 | @isPaneOpened = not @isPaneOpened 68 | height = if @isPaneOpened then PANE_TITLE_HEIGHT_OPEN \ 69 | else PANE_TITLE_HEIGHT_CLOSE 70 | @velocity 71 | properties: 72 | height: height 73 | options: 74 | duration: 100 75 | 76 | # Private: Kill Meteor's process and its subprocess (Mongo). 77 | # 78 | # Returns the [Description] as `undefined`. 79 | _killMeteor: -> 80 | # Kill Meteor's process if it's running 81 | @process?.kill() 82 | # Only kill Mongo if it's Meteor's default one 83 | return unless @mongoURL is '' 84 | # Sometimes Mongo get stuck, force exit it 85 | new BufferedProcess 86 | command: 'killall' 87 | args: ['mongod'] 88 | 89 | # Public static: Format a Meteor log. 90 | # 91 | # str - The log to check and format, if necessary. 92 | # 93 | # Returns Either a raw string or a formated Meteor log in HTML. 94 | @LogFormat = (str) -> 95 | # Remove ANSI colors 96 | raw = str.replace /\\033\\[[0-9;]*m/g, '' 97 | # Check if it's common message or a Meteor log 98 | pattern = /// 99 | ^([I,W]) # Only take I or W 100 | \d{8}- # Remove the date 101 | (\d{2}:\d{2}:\d{2}.\d{3}) # Get the time 102 | \(\d\)\?\s(.*) # Get the reason 103 | /// 104 | found = (raw.match pattern)?[1..3] 105 | return raw unless found 106 | # Format the Meteor log 107 | css_class = if found[0] is 'I' then 'text-info' else 'text-error' 108 | "

#{found[1]} #{found[2]}

" 109 | 110 | # Private: Display default pane. 111 | # 112 | # Returns: `undefined` 113 | _displayPane: -> 114 | # Set an initial message before appending the panel 115 | @paneIconStatus = 'WAITING' 116 | @setMsg 'Launching Meteor...' 117 | # Clear height if it has been modified formerly 118 | @height PANE_TITLE_HEIGHT_CLOSE 119 | @isPaneOpened = false 120 | # Fade the panel in 121 | @velocity 'fadeIn', duration: 100, display: 'block' 122 | # Add the view to the current workspace 123 | atom.workspace.addBottomPanel item: @ 124 | 125 | # Private: Get and check settings. 126 | # Throws Error in case of wrong settings. 127 | # Returns: `undefined` 128 | _getSettings: -> 129 | # Get the configured Meteor's path, port and production flag 130 | @meteorAppPath = atom.config.get 'meteor-helper.meteorAppPath' 131 | @meteorPath = atom.config.get 'meteor-helper.meteorPath' 132 | @meteorPort = atom.config.get 'meteor-helper.meteorPort' 133 | @isMeteorProd = atom.config.get 'meteor-helper.production' 134 | @nodeEnv = atom.config.get 'meteor-helper.nodeEnv' 135 | @isMeteorDebug = atom.config.get 'meteor-helper.debug' 136 | @mongoURL = atom.config.get 'meteor-helper.mongoURL' 137 | @mongoOplogURL = atom.config.get 'meteor-helper.mongoOplogURL' 138 | @settingsPath = atom.config.get 'meteor-helper.settingsPath' 139 | # Check if the command is installed on the system 140 | isCliDefined = fs.existsSync @meteorPath 141 | # Set an error message if Meteor CLI cannot be found 142 | unless isCliDefined 143 | throw new Error "

Meteor command not found: #{@meteorPath}

144 |

You can override these settings in this package preference or in a custom mup.json file.

" 145 | 146 | # Check for project specific settings 147 | mup_project_path = path.join atom.project.getPaths()[0], 'mup.json' 148 | isMupPrjCreated = fs.existsSync mup_project_path 149 | 150 | # Only overwrite settings if a `mup.json` is available 151 | if isMupPrjCreated 152 | try 153 | cnt = fs.readFileSync mup_project_path 154 | mup = JSON.parse cnt 155 | # Overwrite app path if it exists 156 | @meteorAppPath = mup.app if mup.app? 157 | # Overwrite NODE_ENV if it exists 158 | @nodeEnv = mup.env.NODE_ENV if mup.env? and mup.env.NODE_ENV? 159 | catch err 160 | @paneIconStatus = 'WARNING' 161 | @setMsg "

mup.json is corrupted: #{err}. 162 | Default back to current settings.

" 163 | 164 | # Check if the current project owns a Meteor project 165 | meteor_project_path = path.join atom.project.getPaths()[0], @meteorAppPath, '.meteor' 166 | isPrjCreated = fs.existsSync meteor_project_path 167 | 168 | # Set an error message if no Meteor project is found 169 | unless isPrjCreated 170 | throw new Error "

No Meteor project found in:


#{meteor_project_path}" 171 | 172 | # Check if settings path exists 173 | _settingsPath = 174 | if @settingsPath[0] is '/' 175 | @settingsPath 176 | else 177 | path.join atom.project.getPaths()[0], @settingsPath 178 | isSettingsPathValid = fs.existsSync _settingsPath 179 | # Set an error if settings path is invalid 180 | unless isSettingsPathValid 181 | throw new Error " 182 |

Unable to locate settings JSON file at: #{@settingsPath}


183 |

Please make sure the file exists, or remove it from settings.

" 184 | 185 | # Private: Modify process env and parse mup projects. 186 | # 187 | # Returns: `undefined` 188 | _modifyProcessEnv: -> 189 | # Tweek process path to circumvent Meteorite issue: 190 | # https://github.com/oortcloud/meteorite/issues/203 191 | process.env.PATH = "#{process.env.HOME}/.meteor/tools/" + 192 | "latest/bin:#{process.env.PATH}" 193 | # If NODE_ENV is specified, use that 194 | if @nodeEnv? and @nodeEnv isnt '' 195 | process.env.NODE_ENV = @nodeEnv 196 | else 197 | # Check if Meteor should use production mode 198 | if @isMeteorProd 199 | # Set NODE_ENV 200 | process.env.NODE_ENV = 'production' 201 | else 202 | # Unset former uses 203 | delete process.env.NODE_ENV if process.env.NODE_ENV? 204 | # Check if Meteor should use a custom MongoDB 205 | if @mongoURL isnt '' 206 | # Set MongoDB's URL 207 | process.env.MONGO_URL = @mongoURL 208 | else 209 | # Unset former uses 210 | delete process.env.MONGO_URL if process.env.MONGO_URL? 211 | if @mongoOplogURL isnt '' 212 | # Set MongoDB's URL 213 | process.env.MONGO_OPLOG_URL = @mongoOplogURL 214 | else 215 | # Unset former uses 216 | delete process.env.MONGO_OPLOG_URL if process.env.MONGO_OPLOG_URL? 217 | # Check if a specific project file is available which could 218 | # overwrite settings variables 219 | mup_project_path = path.join atom.project.getPaths()[0], 'mup.json' 220 | isMupPrjCreated = fs.existsSync mup_project_path 221 | # Only overwrite settings if a `mup.json` is available 222 | if isMupPrjCreated 223 | try 224 | cnt = fs.readFileSync mup_project_path 225 | mup = JSON.parse cnt 226 | process.env.MONGO_URL = mup.env.MONGO_URL if mup.env?.MONGO_URL? 227 | process.env.MONGO_OPLOG_URL = mup.env.MONGO_OPLOG_URL \ 228 | if mup.env?.MONGO_OPLOG_URL? 229 | @meteorPort = mup.env.PORT if mup.env?.PORT? 230 | catch err 231 | @paneIconStatus = 'WARNING' 232 | @setMsg "

mup.json is corrupted: #{err}. 233 | Default back to current settings.

" 234 | 235 | # Public: Reset Meteor state and Mongo DB. 236 | # 237 | # Returns: `undefined` 238 | reset: => 239 | # Check if Meteor is launched 240 | unless @hasParent() 241 | # Display main pane 242 | @_displayPane() 243 | try 244 | # Get and set settings 245 | @_getSettings() 246 | # Modify process env and check mup files 247 | @_modifyProcessEnv() 248 | @setMsg 'Project reset.' 249 | # Launch Meteor reset 250 | new BufferedProcess 251 | command: @meteorPath 252 | args: ['reset'] 253 | options: 254 | cwd: path.join atom.project.getPaths()[0], @meteorAppPath 255 | env: process.env 256 | @setMsg 'Project reset.' 257 | catch err 258 | @paneIconStatus = 'ERROR' 259 | @setMsg err.message 260 | 261 | # Public: Launch or kill the pane and the Meteor process. 262 | # 263 | # Returns: `undefined` 264 | toggle: => 265 | # Check if Meteor is launched 266 | if @hasParent() 267 | # Fade out the pane before destroying it 268 | @velocity 'fadeOut', duration: 100 269 | setTimeout => 270 | # Detach pane from the editor's view 271 | @detach() 272 | # Kill former process 273 | @_killMeteor() 274 | , 100 275 | return 276 | # Display main pane 277 | @_displayPane() 278 | # Store args 279 | args = [] 280 | try 281 | # Get and check settings 282 | @_getSettings() 283 | # Modify process env and check mup files 284 | @_modifyProcessEnv() 285 | # Check if the production flag needs to be added 286 | args.push '--production' if @isMeteorProd 287 | # Check if Meteor is in debug mode 288 | args.push 'debug' if @isMeteorDebug 289 | # Check if Meteor's port need to be configure 290 | args.push '--port', String @meteorPort if @meteorPort 291 | # Check if settings file should be configured 292 | args.push '--settings', String @settingsPath if @settingsPath 293 | # Launch Meteor 294 | @process = new BufferedProcess 295 | command: @meteorPath 296 | args: args 297 | options: 298 | cwd: path.join atom.project.getPaths()[0], @meteorAppPath 299 | env: process.env 300 | stdout: @paneAddInfo 301 | stderr: @paneAddErr 302 | exit: @paneAddExit 303 | catch err 304 | @paneIconStatus = 'ERROR' 305 | @setMsg err.message 306 | 307 | # Public: Force appearing of the pane 308 | # 309 | # Returns: `undefined` 310 | forceAppear: => 311 | @isPaneOpened = true 312 | @velocity 313 | properties: height: PANE_TITLE_HEIGHT_OPEN 314 | options: duration: 100 315 | 316 | # Public: Set message in pane's details section 317 | # 318 | # msg - The message as String. 319 | # isAppended - A flag for appending or replacing as Boolean. 320 | # 321 | # Returns: `undefined` 322 | setMsg: (msg, isAppended = false) => 323 | switch @paneIconStatus 324 | when 'INFO' 325 | @meteorStatus.html '' 326 | when 'WAITING' 327 | @meteorStatus.html '' 329 | else 330 | @meteorStatus.html '' 332 | # When an error is detected, force appearance of the pane 333 | @forceAppear() 334 | if isAppended 335 | @meteorDetails.append msg 336 | else 337 | @meteorDetails.html msg 338 | console.log '@meteorDetails', @meteorDetails 339 | # Ensure scrolling 340 | @meteorDetails.parent().css('top', 0).scrollToBottom() 341 | 342 | # Patterns used for OK status on Meteor CLI's output 343 | PATTERN_METEOR_OK: /// 344 | App.running.at: # Classic start of Meteor 345 | | remove.dep # Removal of dependencies in Famono 346 | | Scan.the.folder # End of requirements in Famono 347 | | Ensure.dependencies # Generally after having fixed an error 348 | | server.restarted # Fresh code on Meteor's server 349 | | restarting # Sometimes Meteor do use this one 350 | /// 351 | 352 | # Patterns used for error status on Meteor CLI's output 353 | PATTERN_METEOR_ERROR: /// 354 | [E|e]rror # Basic error 355 | | STDERR # Received a console.error 356 | | is.crashing # Server crashing 357 | | Exited.with.code # Another case of server crashing 358 | /// 359 | 360 | # Pattenrs used for detecting unworthy status changes 361 | # (like a simple console.log in the Meteor app) 362 | PATTERN_METEOR_UNCHANGED: /// 363 | I[0-9] # console.log statements starts with I and a date 364 | /// 365 | 366 | # Public: Add info in the pane and determine which type of info to add. 367 | # 368 | # outputs - The Meteor's CLI outputs as String. 369 | # 370 | # Returns: `undefined` 371 | paneAddInfo: (outputs) => 372 | # Iterate over each new non blank lines 373 | # and weird white space extensions in the outputs 374 | tOuputs = outputs.split /\n|\ {8,}/ 375 | for output in tOuputs when output isnt '' 376 | # spare former status 377 | oldstatus = @paneIconStatus 378 | # Check for OK patterns 379 | @paneIconStatus = if output.match @PATTERN_METEOR_OK then 'INFO' 380 | # Check for error patterns 381 | else if output.match @PATTERN_METEOR_ERROR then 'ERROR' 382 | else if output.match @PATTERN_METEOR_UNCHANGED then oldstatus 383 | else 'WAITING' 384 | # Display the message with the appropriare status 385 | msg = "

#{MeteorHelperView.LogFormat output}

" 386 | @setMsg msg, true 387 | 388 | # Public: Add error in the pane 389 | # 390 | # output - The Meteor's output as String. 391 | # 392 | # Returns: `undefined` 393 | paneAddErr: (output) => 394 | msg = "

#{MeteorHelperView.LogFormat output}

" 395 | @paneIconStatus = 'ERROR' 396 | @setMsg msg, true 397 | 398 | # Public: Add exit status in the pane. 399 | # 400 | # code - The Meteor's exit code as Integer. 401 | # 402 | # Returns: `undefined` 403 | paneAddExit: (code) => 404 | # Nullify current process 405 | @process.kill() 406 | @process = null 407 | # Display the exit status 408 | msg = "

Meteor has exited with 409 | status code: #{code}

" 410 | @paneIconStatus = 'ERROR' 411 | @setMsg msg, true 412 | -------------------------------------------------------------------------------- /lib/meteor-helper.coffee: -------------------------------------------------------------------------------- 1 | MeteorHelperView = require './meteor-helper-view' 2 | 3 | module.exports = MeteorHelper = 4 | # Define configuration capabilities 5 | config: 6 | meteorAppPath: 7 | type: 'string' 8 | description: 'The relative path to the Meteor application \ 9 | directory, e.g. "app"' 10 | default: '.' 11 | order: 1 12 | meteorPath: 13 | type: 'string' 14 | description: 'Customize Meteor\'s launching command' 15 | default: '/usr/local/bin/meteor' 16 | order: 2 17 | meteorPort: 18 | type: 'integer' 19 | default: 3000 20 | description: 'Meteor\'s default port is 3000 and Mongo\'s default port \ 21 | is the same incremented by 1' 22 | order: 3 23 | mongoURL: 24 | title: 'Mongo URL' 25 | type: 'string' 26 | default: '' 27 | description: 'Default Mongo installation is generally accessible at: \ 28 | mongodb://localhost:27017' 29 | order: 4 30 | settingsPath: 31 | title: 'Settings Path' 32 | type: 'string' 33 | default: '' 34 | description: 'Relative or absolute path to Meteor.settings JSON file' 35 | order: 5 36 | mongoOplogURL: 37 | title: 'Mongo Oplog URL' 38 | type: 'string' 39 | default: '' 40 | description: 'Default Mongo Oplog installation must match MONGO_URL' 41 | order: 6 42 | debug: 43 | title: 'Run in Debug Mode' 44 | type: 'boolean' 45 | default: false 46 | description: 'Run Meteor in debug mode for connecting from debugging \ 47 | clients, such as node-inspector (port 5858)' 48 | order: 7 49 | production: 50 | title: 'Simulate Production' 51 | type: 'boolean' 52 | default: false 53 | description: 'Simulate running in production by minifying the \ 54 | JS/CSS assets' 55 | order: 8 56 | nodeEnv: 57 | title: 'NODE_ENV' 58 | type: 'string' 59 | default: '' 60 | description: 'Set the NODE_ENV environment variable when running meteor' 61 | order: 9 62 | 63 | meteorHelperView: null 64 | 65 | # Public: Activate plugin 66 | # 67 | # state - The serialized state. 68 | # 69 | # Returns: `undefined` 70 | activate: (state) -> 71 | # Create the main's view 72 | @meteorHelperView = new MeteorHelperView state.meteorHelperViewState 73 | 74 | # Public: Deactivate plugin. 75 | # 76 | # Returns: `undefined` 77 | deactivate: -> 78 | @meteorHelperView.destroy() 79 | 80 | # Public: Serialize package state. 81 | # 82 | # Returns: Seriliazed package. 83 | serialize: -> 84 | meteorHelperViewState: @meteorHelperView.serialize() 85 | -------------------------------------------------------------------------------- /menus/meteor-helper.cson: -------------------------------------------------------------------------------- 1 | 'context-menu': 2 | 'atom-workspace': [{label: 'Launch Meteor', command: 'meteor-helper:toggle'}] 3 | menu: [{ 4 | label: 'Packages' 5 | submenu: [ 6 | label: 'Meteor' 7 | submenu: [ 8 | {label: 'Toggle', command: 'meteor-helper:toggle'} 9 | {label: 'Reset', command: 'meteor-helper:reset'} 10 | {label: 'Show/hide', command: 'meteor-helper:showHide'} 11 | ] 12 | ] 13 | }] 14 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "meteor-helper", 3 | "main": "./lib/meteor-helper", 4 | "version": "0.29.0", 5 | "private": true, 6 | "description": "Launch Meteor from Atom.io", 7 | "repository": { 8 | "type": "git", 9 | "url": "https://github.com/PEM--/meteor-helper" 10 | }, 11 | "license": "MIT", 12 | "engines": { 13 | "atom": ">=1.8.0" 14 | }, 15 | "activationCommands": { 16 | "atom-workspace": [ 17 | "meteor-helper:toggle", 18 | "meteor-helper:reset" 19 | ] 20 | }, 21 | "dependencies": { 22 | "atom-space-pen-views": "^2.2.0", 23 | "velocity-animate": "^1.2.3" 24 | }, 25 | "readmeFilename": "README.md", 26 | "bugs": "https://github.com/PEM--/meteor-helper/issues", 27 | "homepage": "https://github.com/PEM--/meteor-helper", 28 | "keywords": [ 29 | "meteor", 30 | "launcher", 31 | "atom" 32 | ], 33 | "_atomModuleCache": { 34 | "version": 1, 35 | "dependencies": { 36 | "atom-space-pen-views": "^2.2.0", 37 | "velocity-animate": "^1.2.3" 38 | }, 39 | "extensions": { 40 | ".json": [ 41 | "package.json" 42 | ], 43 | ".coffee": [ 44 | "lib/meteor-helper-view.coffee", 45 | "lib/meteor-helper.coffee" 46 | ], 47 | ".less": [ 48 | "styles/meteor-helper.less" 49 | ], 50 | ".cson": [ 51 | "keymaps/meteor-helper.cson", 52 | "menus/meteor-helper.cson" 53 | ], 54 | ".svg": [ 55 | "assets/meteor_logo.svg" 56 | ] 57 | } 58 | } 59 | } 60 | -------------------------------------------------------------------------------- /spec/meteor-helper-spec.coffee: -------------------------------------------------------------------------------- 1 | {WorkspaceView} = require 'atom' 2 | MeteorHelper = require '../lib/meteor-helper' 3 | 4 | # Use the command `window:run-package-specs` (cmd-alt-ctrl-p) to run specs. 5 | # 6 | # To run a specific `it` or `describe` block add an `f` to the front (e.g. `fit` 7 | # or `fdescribe`). Remove the `f` to unfocus the block. 8 | 9 | describe "MeteorHelper", -> 10 | activationPromise = null 11 | 12 | beforeEach -> 13 | atom.workspaceView = new WorkspaceView 14 | activationPromise = atom.packages.activatePackage('meteor-helper') 15 | 16 | describe "when the meteor-helper:toggle event is triggered", -> 17 | it "attaches and then detaches the view", -> 18 | expect(atom.workspaceView.find('.meteor-helper')).not.toExist() 19 | 20 | # This is an activation event, triggering it will cause the package to be 21 | # activated. 22 | atom.workspaceView.trigger 'meteor-helper:toggle' 23 | 24 | waitsForPromise -> 25 | activationPromise 26 | 27 | runs -> 28 | expect(atom.workspaceView.find('.meteor-helper')).toExist() 29 | atom.workspaceView.trigger 'meteor-helper:toggle' 30 | expect(atom.workspaceView.find('.meteor-helper')).not.toExist() 31 | -------------------------------------------------------------------------------- /spec/meteor-helper-view-spec.coffee: -------------------------------------------------------------------------------- 1 | MeteorHelperView = require '../lib/meteor-helper-view' 2 | 3 | describe "MeteorHelperView", -> 4 | it "has one valid test", -> 5 | expect("life").toBe "easy" 6 | -------------------------------------------------------------------------------- /styles/meteor-helper.less: -------------------------------------------------------------------------------- 1 | // See https://github.com/atom/atom-dark-ui/blob/master/stylesheets/ui-variables.less 2 | @import "ui-variables"; 3 | // TODO Does not work @import "../bower_components/font-awesome-animation/dist/font-awesome-animation.css"; 4 | // Manual copy 5 | // ----------- 6 | @-webkit-keyframes wrench{0%{-webkit-transform:rotate(-12deg);transform:rotate(-12deg)}8%{-webkit-transform:rotate(12deg);transform:rotate(12deg)}10%{-webkit-transform:rotate(24deg);transform:rotate(24deg)}18%,20%{-webkit-transform:rotate(-24deg);transform:rotate(-24deg)}28%,30%{-webkit-transform:rotate(24deg);transform:rotate(24deg)}38%,40%{-webkit-transform:rotate(-24deg);transform:rotate(-24deg)}48%,50%{-webkit-transform:rotate(24deg);transform:rotate(24deg)}58%,60%{-webkit-transform:rotate(-24deg);transform:rotate(-24deg)}68%{-webkit-transform:rotate(24deg);transform:rotate(24deg)}75%{-webkit-transform:rotate(0deg);transform:rotate(0deg)}}@keyframes wrench{0%{-webkit-transform:rotate(-12deg);-ms-transform:rotate(-12deg);transform:rotate(-12deg)}8%{-webkit-transform:rotate(12deg);-ms-transform:rotate(12deg);transform:rotate(12deg)}10%{-webkit-transform:rotate(24deg);-ms-transform:rotate(24deg);transform:rotate(24deg)}18%,20%{-webkit-transform:rotate(-24deg);-ms-transform:rotate(-24deg);transform:rotate(-24deg)}28%,30%{-webkit-transform:rotate(24deg);-ms-transform:rotate(24deg);transform:rotate(24deg)}38%,40%{-webkit-transform:rotate(-24deg);-ms-transform:rotate(-24deg);transform:rotate(-24deg)}48%,50%{-webkit-transform:rotate(24deg);-ms-transform:rotate(24deg);transform:rotate(24deg)}58%,60%{-webkit-transform:rotate(-24deg);-ms-transform:rotate(-24deg);transform:rotate(-24deg)}68%{-webkit-transform:rotate(24deg);-ms-transform:rotate(24deg);transform:rotate(24deg)}75%{-webkit-transform:rotate(0deg);-ms-transform:rotate(0deg);transform:rotate(0deg)}}.faa-wrench.animated,.faa-wrench.animated-hover:hover{-webkit-animation:wrench 2.5s ease infinite;animation:wrench 2.5s ease infinite;transform-origin-x:90%;transform-origin-y:35%;transform-origin-z:initial}@-webkit-keyframes ring{0%{-webkit-transform:rotate(-15deg);transform:rotate(-15deg)}2%{-webkit-transform:rotate(15deg);transform:rotate(15deg)}4%{-webkit-transform:rotate(-18deg);transform:rotate(-18deg)}6%{-webkit-transform:rotate(18deg);transform:rotate(18deg)}8%{-webkit-transform:rotate(-22deg);transform:rotate(-22deg)}10%{-webkit-transform:rotate(22deg);transform:rotate(22deg)}12%{-webkit-transform:rotate(-18deg);transform:rotate(-18deg)}14%{-webkit-transform:rotate(18deg);transform:rotate(18deg)}16%{-webkit-transform:rotate(-12deg);transform:rotate(-12deg)}18%{-webkit-transform:rotate(12deg);transform:rotate(12deg)}20%{-webkit-transform:rotate(0deg);transform:rotate(0deg)}}@keyframes ring{0%{-webkit-transform:rotate(-15deg);-ms-transform:rotate(-15deg);transform:rotate(-15deg)}2%{-webkit-transform:rotate(15deg);-ms-transform:rotate(15deg);transform:rotate(15deg)}4%{-webkit-transform:rotate(-18deg);-ms-transform:rotate(-18deg);transform:rotate(-18deg)}6%{-webkit-transform:rotate(18deg);-ms-transform:rotate(18deg);transform:rotate(18deg)}8%{-webkit-transform:rotate(-22deg);-ms-transform:rotate(-22deg);transform:rotate(-22deg)}10%{-webkit-transform:rotate(22deg);-ms-transform:rotate(22deg);transform:rotate(22deg)}12%{-webkit-transform:rotate(-18deg);-ms-transform:rotate(-18deg);transform:rotate(-18deg)}14%{-webkit-transform:rotate(18deg);-ms-transform:rotate(18deg);transform:rotate(18deg)}16%{-webkit-transform:rotate(-12deg);-ms-transform:rotate(-12deg);transform:rotate(-12deg)}18%{-webkit-transform:rotate(12deg);-ms-transform:rotate(12deg);transform:rotate(12deg)}20%{-webkit-transform:rotate(0deg);-ms-transform:rotate(0deg);transform:rotate(0deg)}}.faa-ring.animated,.faa-ring.animated-hover:hover{-webkit-animation:ring 2s ease infinite;animation:ring 2s ease infinite;transform-origin-x:50%;transform-origin-y:0;transform-origin-z:initial}@-webkit-keyframes vertical{0%{-webkit-transform:translate(0,-3px);transform:translate(0,-3px)}4%{-webkit-transform:translate(0,3px);transform:translate(0,3px)}8%{-webkit-transform:translate(0,-3px);transform:translate(0,-3px)}12%{-webkit-transform:translate(0,3px);transform:translate(0,3px)}16%{-webkit-transform:translate(0,-3px);transform:translate(0,-3px)}20%{-webkit-transform:translate(0,3px);transform:translate(0,3px)}22%{-webkit-transform:translate(0,0);transform:translate(0,0)}}@keyframes vertical{0%{-webkit-transform:translate(0,-3px);-ms-transform:translate(0,-3px);transform:translate(0,-3px)}4%{-webkit-transform:translate(0,3px);-ms-transform:translate(0,3px);transform:translate(0,3px)}8%{-webkit-transform:translate(0,-3px);-ms-transform:translate(0,-3px);transform:translate(0,-3px)}12%{-webkit-transform:translate(0,3px);-ms-transform:translate(0,3px);transform:translate(0,3px)}16%{-webkit-transform:translate(0,-3px);-ms-transform:translate(0,-3px);transform:translate(0,-3px)}20%{-webkit-transform:translate(0,3px);-ms-transform:translate(0,3px);transform:translate(0,3px)}22%{-webkit-transform:translate(0,0);-ms-transform:translate(0,0);transform:translate(0,0)}}.faa-vertical.animated,.faa-vertical.animated-hover:hover{-webkit-animation:vertical 2s ease infinite;animation:vertical 2s ease infinite}@-webkit-keyframes horizontal{0%{-webkit-transform:translate(0,0);transform:translate(0,0)}6%{-webkit-transform:translate(5px,0);transform:translate(5px,0)}12%{-webkit-transform:translate(0,0);transform:translate(0,0)}18%{-webkit-transform:translate(5px,0);transform:translate(5px,0)}24%{-webkit-transform:translate(0,0);transform:translate(0,0)}30%{-webkit-transform:translate(5px,0);transform:translate(5px,0)}36%{-webkit-transform:translate(0,0);transform:translate(0,0)}}@keyframes horizontal{0%{-webkit-transform:translate(0,0);-ms-transform:translate(0,0);transform:translate(0,0)}6%{-webkit-transform:translate(5px,0);-ms-transform:translate(5px,0);transform:translate(5px,0)}12%{-webkit-transform:translate(0,0);-ms-transform:translate(0,0);transform:translate(0,0)}18%{-webkit-transform:translate(5px,0);-ms-transform:translate(5px,0);transform:translate(5px,0)}24%{-webkit-transform:translate(0,0);-ms-transform:translate(0,0);transform:translate(0,0)}30%{-webkit-transform:translate(5px,0);-ms-transform:translate(5px,0);transform:translate(5px,0)}36%{-webkit-transform:translate(0,0);-ms-transform:translate(0,0);transform:translate(0,0)}}.faa-horizontal.animated,.faa-horizontal.animated-hover:hover{-webkit-animation:horizontal 2s ease infinite;animation:horizontal 2s ease infinite}@-webkit-keyframes flash{0%,100%,50%{opacity:1}25%,75%{opacity:0}}@keyframes flash{0%,100%,50%{opacity:1}25%,75%{opacity:0}}.faa-flash.animated,.faa-flash.animated-hover:hover{-webkit-animation:flash 2s ease infinite;animation:flash 2s ease infinite}@-webkit-keyframes bounce{0%,10%,20%,50%,80%{-webkit-transform:translateY(0);transform:translateY(0)}40%,60%{-webkit-transform:translateY(-15px);transform:translateY(-15px)}}@keyframes bounce{0%,10%,20%,50%,80%{-webkit-transform:translateY(0);-ms-transform:translateY(0);transform:translateY(0)}40%,60%{-webkit-transform:translateY(-15px);-ms-transform:translateY(-15px);transform:translateY(-15px)}}.faa-bounce.animated,.faa-bounce.animated-hover:hover{-webkit-animation:bounce 2s ease infinite;animation:bounce 2s ease infinite}@-webkit-keyframes spin{0%{-webkit-transform:rotate(0deg);transform:rotate(0deg)}100%{-webkit-transform:rotate(359deg);transform:rotate(359deg)}}@keyframes spin{0%{-webkit-transform:rotate(0deg);-ms-transform:rotate(0deg);transform:rotate(0deg)}100%{-webkit-transform:rotate(359deg);-ms-transform:rotate(359deg);transform:rotate(359deg)}}.faa-spin.animated,.faa-spin.animated-hover:hover{-webkit-animation:spin 1.5s linear infinite;animation:spin 1.5s linear infinite}@-webkit-keyframes float{0%{-webkit-transform:translateY(0);transform:translateY(0)}50%{-webkit-transform:translateY(-6px);transform:translateY(-6px)}100%{-webkit-transform:translateY(0);transform:translateY(0)}}@keyframes float{0%{-webkit-transform:translateY(0);-ms-transform:translateY(0);transform:translateY(0)}50%{-webkit-transform:translateY(-6px);-ms-transform:translateY(-6px);transform:translateY(-6px)}100%{-webkit-transform:translateY(0);-ms-transform:translateY(0);transform:translateY(0)}}.faa-float.animated,.faa-float.animated-hover:hover{-webkit-animation:float 2s linear infinite;animation:float 2s linear infinite}@-webkit-keyframes pulse{0%{-webkit-transform:scale(1.1);transform:scale(1.1)}50%{-webkit-transform:scale(0.8);transform:scale(0.8)}100%{-webkit-transform:scale(1.1);transform:scale(1.1)}}@keyframes pulse{0%{-webkit-transform:scale(1.1);-ms-transform:scale(1.1);transform:scale(1.1)}50%{-webkit-transform:scale(0.8);-ms-transform:scale(0.8);transform:scale(0.8)}100%{-webkit-transform:scale(1.1);-ms-transform:scale(1.1);transform:scale(1.1)}}.faa-pulse.animated,.faa-pulse.animated-hover:hover{-webkit-animation:pulse 2s linear infinite;animation:pulse 2s linear infinite}.faa-shake.animated,.faa-shake.animated-hover:hover{-webkit-animation:wrench 2.5s ease infinite;animation:wrench 2.5s ease infinite} 7 | // ----------- 8 | 9 | // Define specific style for Meteor package 10 | .meteor-helper { 11 | height: 25px; 12 | display: none; 13 | 14 | .panel-heading { 15 | background-color: @tool-panel-background-color; 16 | background-image: none; 17 | padding: 0 15px; 18 | height: 26px; 19 | 20 | .meteor-logo { 21 | width: 76px; 22 | height: 25px; 23 | background-position: 5px 0; 24 | background-repeat: no-repeat; 25 | background-size: 100px 17px; 26 | background-image: url("atom://meteor-helper/assets/meteor_logo.svg"); 27 | } 28 | 29 | .status-bar-right { 30 | margin-top: 5px; 31 | width: 18px; 32 | height: 18px; 33 | text-align: center; 34 | span.icon-check:before, span.icon-alert:before, span.icon-gear:before { 35 | text-align: center; 36 | margin: 0; 37 | padding: 0; 38 | border: 0; 39 | font-size: 14px; 40 | line-height: 14px; 41 | width: 14px; 42 | height: 14px; 43 | } 44 | } 45 | } 46 | 47 | .panel-body { 48 | // Avoid beeing to close to the pannel left and right border 49 | margin: 0 15px; 50 | // Ensure enough space for displaying all messages 51 | padding-bottom: 25px; 52 | // Make its content scrollable 53 | overflow-x: hidden; 54 | overflow-y: auto; 55 | height: inherit; 56 | min-height: 2rem; 57 | // Remove margin on h3 as they are used to display big warning text 58 | h3 { 59 | padding-top: 2px; 60 | padding-left: 4px; 61 | margin: 0; 62 | } 63 | .meteor-details { 64 | padding-top: 5px; 65 | padding-left: 4px; 66 | margin: 0; 67 | } 68 | // Reduce margin bottom inherited from Bootstrap 69 | p { 70 | margin: 0; 71 | } 72 | } 73 | } 74 | --------------------------------------------------------------------------------