/sublime-browser-integration

A Sublime Text 3 plugin for interacting with the browser and do developer related tasks.

Primary LanguagePythonMIT LicenseMIT

Browser Integration

A Sublime Text 3 plugin for interacting with the browser and perform web development related tasks.

Disclaimer:

This plugin is in development state, which means is unstable, and it might not work in your system. It should work with Google Chrome and Chromium Browser versions 31 to 34, and modern versions of Firefox, on modern versions of Linux, MacOSX and Windows, but it has only been tested so far with:

  • Ubuntu Linux 13.10 x86 + ST3 (3059) + Chrome 31
  • Windows 8 x64 + ST3 (3047) + Chrome 32

Current iterations are constantly changing the names, key bindings, and semantics of most commands, so every time you upgrade, something will likely not work the way it used to. Sorry for the inconvenience, I'm working as hard as possible to get a stable version out, but it will take me some time...

What is this?

This plugin fires up a browser (Chrome and Firefox only, for now), and keeps a connection open with it, that allows you to send commands and control to the browser from within ST3.

I made this plugin inspired by the work of Bret Victor and his idea of multimedia connection. Basically, it means that developers should be as close as possible to their creations, and I wasn't happy with the current level of connectivity I can reach in my web development environment.

As web developers, must of the time we work in two different environments: our text editor, and the browser. We have to constantly change form typing code to refreshing the browser, from test short scripts in the browser's development console to writing more complex scripts in the server, from inspecting DOM elements and changing CSS in the browser, to go back to the text editor and figure out where those new CSS rules fit in.

This plugin is my attempt to bring both tools a little closer, and create a connection between browser and text editor that really lets you feel you are working with a single connected tool, not two disconnected different pieces of technology.

Note: The plugin is being actively developed with Chromium. Support for other browser(s) is experimental. Use at your own risk.

Installation

The recommended method is using Sublime Package Control. If you don't know it, go check it out.

You can also clone directly from Github, or download a zip, and unpack it in your Sublime Text 3 packages folder. If you don't know how to do this, you definitely need the Package Control plugin.

Besides that, you need a recent version of Chrome (31 to 34) and the Chrome WebDriver executable. Upon installation of the plugin, it will attempt to download the right executable for your platform (its about 5~10 MBs) directly from sublime.apiad.net and place it in the same folder as the plugin (this only has to be done once). If this doesn't work, you can try to download it manually, rename it to chromedriver, place it alongside the *.sublime-package file (it should be in the root of either your Packages/ folder or your Installed Packages/ folder), and give it execution permissions. If this happens to you, please consider filling up the corresponding issue to help me improve the plugin.

Configuration

Hit ctrl+shift+p and go to 'Browser Integration: Settings (Default)' to read (and possible change) all available configuration parameters.

Features:

Right now, this is what it can do:

Main Menu

Key binding: ctrl+alt+shift+b

Opens a menu panel, where you can find all available commands, navigate, view descriptions, etc. If in doubt, start here. All commands are accessible through this menu, but most of them also have direct key bindings.

The first command is always Launch Browser. This is a necessary step before running any other browser-related command.

Launch Browser

Key binding: ctrl+shift+b,l

Opens a quick panel to select a browser to open. Right now it displays Chrome and Firefox. Select one to launch it. All other browser commands require this one to be called first, and will complain (in your status bar) if the browser is not open, or if the plugin has lost the connection somehow.

After the browser has been opened, the main menu will show more commands. You can directly interact with the opened browser, create new tabs, click in stuff, etc. However, only the first opened tab will be controlled by the plugin, and if closed, connection will be lost and you'll need to launch the browser again. A browser instance can only be controlled if opened through this command, it will not work with an already opened browser.

After opening the browser, it will navigate automatically to your configured starting page. This can changed in the default configuration, under the startup_location settings.

Reload

Key binding: ctrl+shift+b,r

Reloads the browser. You can configure the reload_on_save setting to automatically invoke this command upon save. The reload_on_save_selectors contains a list of regular expressions. Every time you save a file, if its filename matches any of the regular expressions, the browser will be reloaded. By default this options are set so to reload upon saving any HTML, CSS or JavaScript file.

Navigate To

Key binding: ctrl+shift+b,n

If there are links (a tags with the href property defined) in the current page, a quick panel will display all the available links. Selecting any of them will make the browser navigate to it.

The first three options are special links. The first option (Custom URL) opens an input panel to enter a custom URL to navigate to. The currently loaded URL is already selected in the input panel. If you don't type a valid locator (http, https, etc.), then http:// is appended to the URL. The second (Back) and third (Forward) option allow you to navigate back and forth respectively.

Execute

The commands in this submenu allow you to inject code and data into the browser.

Execute :: Selected code

Key binding: ctrl+shift+b,e,c

Takes the selected JavaScript source and runs it in the browser. If the code returns something, it will be opened in a new tab. This is done independently for every selected region, and will open as many tabs as necessary, for every selected piece of script that returns something.

View

The commands in this submenu allow you to load and modify (sometimes live) document data. So far, this are the options:

View :: StyleSheets (CSS)

Key binding: ctrl+shift+b,v,c

Opens a quick panel with the list of all stylesheets that are currently loaded in the browser. Imported stylesheets (link tags) are listed by URL. Embedded stylesheets (style tags) are listed independently, with a small preview of the style code. Upon selecting one of the entries, a new tab is openned with the content of the stylesheet.

If it was an imported stylesheet, the plugin will try to automagically locate the corresponding static file in your project folders. To do that, you have to define mappings that allow the plugin to correlate hrefs with file names. The static_files_mapping settings option does just that using regular expressions. Its default value is:

"static_files_mapping": [
    // Django-style matches.
    // Links like `http://localhost:8000/static/path/to/style.css`
    // will match all your internal projects `/static/` dirs,
    // but **not** the external `static/` folder where Django
    // collects static files.
    {
        "selector": "^http[s]?://localhost:\\d+/static/(.*)\\.css$",
        "matches": [
            "^(.+)/static/\\1.css$"
        ]
    },
    // Exact matches.
    // Links like `http://localhost:8000/path/to/style.css` will
    // match exactly those file paths in your project folders.
    {
        "selector": "^http[s]?://localhost:\\d+/(.*)\\.css$",
        "matches": [
            "^\\1.css$"
        ]
    }
]

If you know something about regular expressions you will easily see what's going on. A selector is tested against an href, and if it matches, then the project folders are searched for filenames matching the corresponding regular expressions. Back substitutions are allowed. The first matching filename will be opened. If no file matches, then the command will attempt to download the link tag's href property, and open it in a new tag.

Right now I'm working on the live editing of these mapped CSS files, with automatic asynchronous browser reload, something I'm very excited of, but still trying to get to work.

If it was embedded, the command will copy the innerHTML property of the style tag, and paste it in a new tab. Modifying the content of an embedded CSS stylesheet will automagically (and asynchronously) reload the stylesheet innerHTML property on the browser.

View :: Page Source

Key binding: ctrl+shift+b,v,s

Opens the document source in a new tab. I've played with implementing live modification of this page source, and its certainly possible but it seems rather useless. Most of the time in web development you don't write raw HTML, but rather rely on some templating engine, so the source code is only used to see if the output is as expected, but hardly ever modified.

View :: LocalStorage Content

Key binding: ctrl+shift+b,v,l

Opens a new document with the content of the localStorage. If the values in your localStorage are JSON-encoded objects, they will be decoded in the new buffer. Modifying the content of this buffer will automagically change the content of the localStorage to match the buffer content, as long as it is a valid JSON file. You don't need to save the buffer for changes to reflect on the browser, instead they are update as you type.

Note: For safety reasons, content put in the localStorage by the plugin is not dumped back. The data put by the plugin in the localStorage is stored in keys that begin with '__bi_', so please, refrain from using keys with such a prefix.

Interact

The commands in this submenu allow to directly interact with the DOM elements.

Interact :: Select by CSS

Key binding: ctrl+shift+b,i,s

Opens an input box, where you can type any valid CSS selector. Matching items are highlighted in the browser as you type, and stay highlighted after you close. These selected elements can be used in other commands, to make specific DOM manipulations. To unselect, launch the command again, and clear the input panel.

Interact :: Select by XPath

Key binding: ctrl+shift+b,i,x

The same as before, but now you can enter an XPath expression.

Interact :: Interactive Selection

Key binding: ctrl+shift+b,i,i

Opens a quick panel which contains a tree representation of the DOM. You can browse the panel and select a specific node to highlight it and select it. Press ENTER on a node to browse its children. The currently selected node is automatically highlighted on the browser.

If you have previously selected any by any way DOM elements, the following commands will allow you to make modifications to those elements. These commands will only appear in the main menu if you have selected elements.

Interact :: Click selected elements

Key binding: ctrl+shift+b,i,c

Sends a click to selected elements.

Interact :: Type into selected elements

Key binding: ctrl+shift+b,i,t

Opens an input box to type a text, that will be sent to the browser and typed into the selected elements.

Interact :: Change selected elements class

Key binding: ctrl+shift+b,i,s

Open an input box with the value of the class attribute of selected elements. If there are more than one selected element, with different classes, the input box will show the union of the elements class attributes. Typing into the input panel will update the selected elements class attribute in real-time.

Macro

The commands in this submenu allow you to record, save and replay browser interaction sessions. With these commands in combination you can easily automatize boring tasks. For instance, every time I work on my site's project, I open ST3, start my development server, open Chrome, navigate to localhost:9090, type in my credentials, and then I can start developing.

Macro :: Record macro

Key binding: ctrl+shift+b,m,r

Begins recording browser interactions. Right now the plugin records Mouse and key inputs. For mouse, only mouse down and mouse up of the left mouse button are recored so far. For key inputs, it has only been tested with alphanumeric keys. The plugin also records on which DOM element the interaction took place, and, on mouse inputs, the relative coordinates of mouse position to the such element.

The events data is saved to the localStorage, so try not to exceed yourself in recording extremely long macros. A few thousand interactions are OK.

Note: When recording macro there are a few things you cannot do, either in ST3 and the browser. In particular, most of the other commands (of this plugin only) will not work as expected, and might delay until the recording is over, or do something weirder. This is due to the recording process, which involves the constant executing of some JavaScript. For the same reason, you cannot open the browser development console during recording (well, you can, but it will close almost instantly). I'm currently working on ways to alleviate this, sorry for the inconvenience.

Macro :: Stop recording

Key binding: ctrl+shift+b,m,s

Collects all macro recording data, to review it and save it in ST3. If there is any data (events) recorded, an input panel will be shown to enter a name for the macro, and after pressing ENTER the macro data will be shown on a new file. This data is a JSON object that contains all necessary information to replay the recorded events. You can save then save the document anywhere in your project's directory for later replay.

Macro :: Play macro

Key binding: ctrl+shift+b,m,p

Finds all .macro files in your project's directory, and shows them in a list. Selecting one of them will replay all the events that where recorded in the macro.

Warning: The saved macro data consists only of DOM events. It has no idea of where or when was the macro recorded. If it finds elements in the current page that fit the description of the recorded events, it will replay them. If you record a macro against some page, and then replay it in some other page, take into account which elements will get clicked or typed! You know what they say: With great power comes great responsibility.

Macro :: Play macro (with delays)

Key binding: ctrl+shift+b,m,d

The same as before, but this time the delays between events is reproduced. This is useful if you recorded the macro against a page that has animations or other complicated interactions. Playing the macro without delays might cause an incorrect behavior because some elements might not appear immediately, and the macro would fail. This command uses time.sleep for waiting, so replayed events might have exactly the same delay as the originals, but it should suffice for most cases. To avoid unnecessary waits, no delay is performed when the recored delay is under 10 milliseconds.

Close Browser

Key binding: ctrl+shift+b,q

Closes the current browser instance, as expected.

How does it work?

The plugin ships with a modified version of selenium for Python, which does the browser controlling magic. That and a few handy JavaScript and Python gets the work done.

What's next?

I'm working on a few exciting new features:

  • Live CSS editing.
  • Improved macro recording and playing.
  • Support for other browsers (Firefox, Opera, perhaps even IE).
  • And many more...

Collaborating

Sure, come to Github.

There are many ways to collaborate: just by trying it out and filling up any issues, it will be of great help. It's very hard to develop a multi-platform Sublime Text plugin, specially when you have to deal with different implementations of browsers, and I can not possible test every combination of Sublime Text + Browser + OS out there, so beta testing is the most precious help you can offer.

If you want to put some code into the plugin, then even better! As usual, fork it, and make your pull request. I'm eager to see what other awesome developers like you come up with... ;)

You can also suggest changes, features, and any interesting idea.