April 2012
My first Chrome extension Save CSS is now available in the Chrome web store!
If you are a web developer working with CSS or Javascript and using the great built-in Developer tools in the Chrome browser, then this extension can improve your workflow a lot. I know it has boosted my own work.
In a typical workflow of web user interface development, you write a little
bit of HTML, Javascript and CSS, then view the result live in a browser
where
you continue tweaking the CSS
with Developer tools in Chrome/Safari or with
Firebug in Firefox. When all the tweaks are finished, you then copy the
modified CSS values manually
one by one and paste them back into your editor,
save all files, and finally view the results again
in a browser to verify that
you remembered to copy everything. You repeat these steps a hundred times a
day. Clearly there is room for improvement.
This extension speeds up the workflow by eliminating the manual copy paste
part and by automatically saving your CSS and Javascript modifications
done
in Developer tools into the original source files in your local disk.
I have been using this extension privately since October 2011 when the experimental APIs became available in early Dev versions of Chrome. The API became officially supported this week when Chrome 18 was released and I was finally able to publish this extension in the Chrome store.
Fire up your Chrome browser and install the extension from the Chrome web store.
Then download the required Python script or Ruby script to your
computer, either one, it doesn't matter since they are identical in
functionality. Run the script from any folder: python server.py
or ruby
server.rb
. The script starts a small web server that actually writes the
changes sent by Chrome into the local disk since Chrome can't save files for
security reasons.
Of course, first make sure you have either Python or Ruby installed on your computer. The scripts do not require any additional libraries to install.
After installation, launch Developer Tools in Chrome. The extension user
interface is visible as the last tab, "Save"
:
Then browse to the site whose CSS or Javascript you want to modify. Most likely you run the development server on local computer and you have all the source files in the local file system.
Now change any CSS property in the Elements-tab, go to Save-tab and you will see an error that says no mapping found. The extension issues an error since it doesn't yet know where to save the changes to. You need to add a mapping rule for the site to map an URL to a local path.
Click Create and a new mapping will be added with a prefilled URL. Remove the file name part from the URL, and enter an absolute path to a local folder where the files are saved to. This path should point to the folder where you store your CSS and Javascript files of your site.
Finally click Save and the mapping gets saved.
Now change a CSS again in the Elements-tab. If everything was configured correctly, the CSS was saved into local disk and you should see an entry in the "Saved Files" table. If not, you should see an error.
Here's a screenshot with one mapping and two successful saves:
All the standard Chrome Developer Tools operations are available for CSS and Javascript tweaking. Here's the summary of what you can do:
To change a CSS property,
double-click either on the property name or the
value and edit the value with a keyboard. Remember that arrow up and down can
change numeric values.
To add a new CSS property,
double-click on the last line of a selector, the one
with "}", and start typing a new property name.
To delete a CSS property,
double-click on the property name and delete the
whole name and press enter.
To add a new CSS selector,
go to the Resources tab and select the desired CSS
file (remember the shortcut link in the Elements tab too). Double-click and
edit the CSS file as you wish. When you press CMD-S, the whole file is saved
and CSS becomes active.
To change Javascript code,
go to the Resources tab and select the desired
Javascript file. Edit and save the whole file with CMD-S. Note that in Chrome,
there is no need to reload the page
since the V8 engine compiles Javascript
just in time.
And don't be afraid of loosing your comments in the CSS or Javascript files -
comments are preserved by Chrome
. Even vendor prefixes are properly
preserved
. Chrome provides solid piece of tech.
The extension doesn't work with CSS compilation setups like LESS since the extension operates at the level of raw CSS and not at the higher level.
If you want to be careful with your CSS/JS tweakings, you can disable the automatic save functionality by unchecking the checkbox at the bottom of the "Save" tab. Then you can control when to save and what files to save. I'm not sure how useful this option is but it's there.
The extension relies on the following devtools API of Chrome:
// request browser to call us when CSS or JS is changed by dev tools
chrome.devtools.inspectedWindow.onResourceContentCommitted.addListener(
function(resource, content) {
// CSS or JS was changed, we got the content
// content: the body of CSS or JS file
// resource.url: the url of file
// resource.type: type of file (css, javascript, document)
});
This powerful API became officially supported in Chrome 18 in March 28, 2012.
The API is very simple: whenever a CSS or Javascript file is modified in the Developer tools, this callback gets called in the extension. The whole content of the CSS or Javascript file is provided, and all the hard work of merging new changes in has been done by Chrome.
Since Chrome extensions do not have access to the local file system,
the write
operation needs to be done externally. The extension thus sends the content
to an external script via AJAX. Being a Python developer, I wrote the script
in Python. The script just receives the content and an absolute destination
file path, and writes the file to disk. In case of error, it returns a
message.
The external script is simple since all the configurations are taken care of by the extension. Mappings are stored permanently into localstorage which is private to the extension.
The whole source code to the extension and to the Python and Ruby web server scripts are available in GitHub.
I'm a long-time Python developer but wrote the script also in Ruby for the fun of it. Here they are both side by side, like twin brothers.
Server scripts in Python and Ruby:
#!/usr/bin/python
# -*- coding: utf-8 -*-
# server.py: receive CSS and JS files from Chrome extension
# and save files locally
#
# Author: Tomi.Mickelsson@iki.fi
# 30.10.2011 - Created
from BaseHTTPServer import HTTPServer, BaseHTTPRequestHandler
class MyServer(BaseHTTPRequestHandler):
def do_POST(self):
hd = self.headers
# chrome sent data:
url = hd.get("X-origurl")
fpath = hd.get("X-filepath")
bodylen = int(hd['content-length'])
body = self.rfile.read(bodylen)
print url, " ->", fpath, len(body)
reply = "OK"
# save file
try:
f = open(fpath, "w")
f.write(body)
f.close()
except Exception, e:
print e
reply = "Server couldn't save "+fpath
# return reply
self.send_response(200)
self.end_headers()
self.wfile.write(reply)
# start http server
server = HTTPServer(('localhost', 8080), MyServer)
print "Server running in port 8080..."
server.serve_forever()
#!/usr/bin/ruby
# -*- coding: utf-8 -*-
# server.rb: receive CSS and JS files from Chrome extension
# and save files locally
#
# Author: Tomi.Mickelsson@iki.fi
# 04.02.2012 - Created
require 'webrick'
include WEBrick
class MyServlet < HTTPServlet::AbstractServlet
def do_POST(req, res)
url = req.header['x-origurl']
fpath = req.header['x-filepath']
bodylen = req.header['content-length']
raw = req.body
fpath = fpath.join("")
print url, " -> ", fpath, " ", bodylen, "\n"
reply = "OK"
# save file
begin
f = File.open(fpath, "wb")
f.syswrite(raw)
f.close
rescue => e
puts "EXCEP " + e.message
reply = e.message
end
res.status = "200"
res.body = reply
end
end
# start server
server = HTTPServer.new(:BindAddress => "localhost",:Port => 8080)
server.mount('/', MyServlet)
trap 'INT' do server.shutdown end
puts "Server running in port 8080..."
server.start
If you have issues with the extension, you can report them below or at GitHub.
Update: The Python script added extra line feeds on Windows. Fixed.
Back