Hire Me! I'm currently looking for my next role in developer relations and advocacy. If you've got an open role and think I'd be a fit, please reach out. You can also find me on LinkedIn.

Over the weekend I was working on a small project and needed a copy of jQuery. I try to avoid the CDN as I find myself at airports without wifi access sometimes so I did what I normally do:

  • Go to jQuery.com
  • Click the download link
  • Click for the latest minified version
  • Right click, save as
That's what I always do - but it kinda bugs me. I had heard of a tool called Bower that I thought might help. It's a package manager for the web. In theory, it would do what I wanted. I went to the command line, installed it via npm (have I said before how much npm rocks?), and then fetched a copy of jQuery like so: bower install jquery.

This worked - and it was epic cool - until I realized how much it grabbed...

Ugh. Don't get me wrong - this was still quicker then my old process. And I "get" the idea behind the metadata involved here and why it would be useful in the future. Bower is pretty damn powerful and I definitely recommend folks take a look at it.

But what if you just want a copy of the library, one time, and that's it?

I decided to whip up a quick Brackets extension as a proof of concept. Clicking the "Run JSDownloader" menu option opens up a dialog of options:

Clicking the library fires off a process to download it:

And yeah... that's it. Simple, direct, exactly what I need. There's a few caveats though.

Right now it only supports "single file" downloads. I've got basic architecture in there to support a list of files, but it isn't complete. The idea is that if you provide a list of files, it will create a subdirectory based on the name of the library (as in: currentdir/jqueryui/) and then copy the resources there. But this isn't complete yet because...

The second issue is that Brackets still doesn't support binary file writes in extensions. In theory I could do so if I hook up a Node module to my extension, but... honestly it feels like a bit much. I'd rather just wait a bit and hope for support in a future sprint.

Finally, there is no support in Brackets yet for refreshing the project view. So while the extension certainly works, you need to do a reload to see the files show up.

So - where did that last of four projects come from? This is kinda cool I think. In order to "drive" the data list, my extension reads from a simple JSON packet. Here's how it looks now:

[
{"key":"jquery","name":"jQuery 2.0","file":"http://code.jquery.com/jquery-2.0.0.min.js"},
{"key":"handlebars","name":"Handlebars 1.0.0 rc3","file":"https://raw.github.com/wycats/handlebars.js/1.0.0-rc.3/dist/handlebars.runtime.js"},
{"key":"underscore","name":"Underscore 1.4.4","file":"http://underscorejs.org/underscore-min.js"},
{"key":"zepto","name":"Zepto 1.0", "file":"http://zeptojs.com/zepto.min.js"}
]
view raw gistfile1.json hosted with ❤ by GitHub

While this file is in the extension itself, my code reads the GitHub version of it instead:

var JSDownloader = (function() {
var INDEX_URL = "https://raw.github.com/cfjedimaster/brackets-jsdownloader/master/jsdownloader_index.json";
var INDEX_KEY = "jsdownloader.index";
//Number of minutes to cache
var CACHE_LEN = 1000*60*60*24;
var index;
return {
getIndex:function() {
var raw = JSON.parse(localStorage.getItem(INDEX_KEY));
return raw.index;
},
hasCachedIndex:function() {
var cache = localStorage.getItem(INDEX_KEY);
if(!cache) return false;
var ob = JSON.parse(cache);
var then = new Date(ob.created);
var now = new Date();
if((now.getTime() - then.getTime()) > CACHE_LEN) return false;
return true;
},
loadIndex:function(cb) {
$.get(INDEX_URL, {}, function(res,code) {
console.dir(res);
var ob = {};
ob.created = new Date();
ob.index = res;
localStorage.setItem(INDEX_KEY, JSON.stringify(ob));
cb();
},"json");
}
};
}());
view raw gistfile1.js hosted with ❤ by GitHub

This means folks could add a new library by just committing to my GitHub repo. I don't have a nice UI to refresh the cache, but if folks end up using and contributing to this extension, I'll add it.

Download/Fork the code here: https://github.com/cfjedimaster/brackets-jsdownloader