Leaner, meaner dotjs #19

Closed
wants to merge 12 commits into
from
View
@@ -17,10 +17,10 @@ GreaseMonkey user scripts are great, but you need to publish them somewhere and
$ cat ~/.js/github.com.js
// swap github logo with trollface
- $('#header .logo img')
- .css('width', '100px')
- .css('margin-top', '-15px')
- .attr('src', '//bit.ly/ghD24e')
+ $('#header .site-logo img')
+ .css('width', '100px')
+ .css('margin-top', '-15px')
+ .attr('src', 'https://img.skitch.com/20110207-x4s8eys3uy641yk72jigt38bby.png');
![](https://dl.dropbox.com/u/361064/dotjs.png)
View
@@ -1,20 +1,35 @@
-(function($) {
- self.on("message", function(msg) {
+/*
+ * catch the 'load-scripts' event and inject the resilts into the current scope.
+ */
+(function() {
+ self.port.on("load-scripts", function(msg) {
+ // bail out if we're in an iframe
+ if (window.frameElement) return;
+
+ if (msg.jquery) {
+ eval(msg.jquery);
+ }
+
if (msg.js) {
eval(msg.js);
}
+
if (msg.coffee) {
(function() {
eval(msg.transpiler);
}).call(window); // coffee-script.js assumes this === window
eval(CoffeeScript.compile(msg.coffee));
}
+
if (msg.css) {
- $('head').append($('<style>').text(msg.css));
+ var headNode = document.querySelector('head');
+ var cssNode = document.createElement('style');
+ cssNode.innerHTML = msg.css;
+ headNode.appendChild(cssNode);
}
});
- // we only operate on http urls? what about chrome or resource?
+
if (document.URL.indexOf('http') === 0) {
- self.postMessage(document.URL);
+ self.port.emit('init', document.URL);
}
-}(jQuery.noConflict(true)));
+})();
View
@@ -0,0 +1,53 @@
+const {Cc, Ci} = require('chrome');
+const data = require("self").data;
+const file = require('file');
+const dirSvc = Cc['@mozilla.org/file/directory_service;1'].getService(Ci.nsIProperties),
+homeDir = dirSvc.get('Home', Ci.nsIFile).path,
+jsDir = homeDir.indexOf('/') === 0 ? '.js' : 'js';
+cssDir = homeDir.indexOf('/') === 0 ? '.css' : 'css';
+
+/**
+ * matchFile: takes the domain name and returns an object with the correct matching
+ * content scripts
+ */
+exports.matchFile = function (domain) {
+ /*
+ * This is a problem - if the user has a default.js/css file, we will always inject
+ * causing a bunch of overhead for each tab.
+ */
+ let files = ['default', domain];
+
+ // our return object
+ let ret = {match: false};
+
+ let jsmatch = false;
+
+ for (var i = files.length - 1; i >= 0; i--) {
+ let filename = file.join(homeDir, jsDir, files[i]);
+
+ if (file.exists(filename + '.js')) {
+ ret.js = file.read(filename + '.js');
+ jsmatch = true;
+ ret.match = true;
+ }
+
+ if (file.exists(filename + '.coffee')) {
+ ret.transpiler = data.load('coffee-script.js');
+ ret.coffee = file.read(filename + '.coffee');
+ jsmatch = true;
+ ret.match = true;
+ }
+
+ let cssname = file.join(homeDir, cssDir, files[i]);
+ if (file.exists(cssname + '.css')) {
+ ret.css = file.read(cssname + '.css');
+ ret.match = true;
+ }
+ }
+
+ // we always load jQuery is there is a JS match.
+ if (jsmatch === true)
+ ret.jquery = data.load('jquery-1.7.1.min.js');
+
+ return ret;
+}
View
@@ -1,52 +1,25 @@
-var tabs = require("tabs"),
- data = require('self').data,
- file = require('file'),
+const data = require('self').data,
url = require('url'),
- {Cc, Ci} = require('chrome');
+ matchFile = require("dotjs").matchFile;
-tabs.on('ready', function(tab) {
- // test for the worker as a property of the tab object.
- if (typeof(tab._dotjs_worker) === 'undefined') {
- let worker = tab.attach({
- contentScriptFile: [data.url('jquery-1.7.1.min.js'), data.url('dotjs.js')]
- });
+require("page-mod").PageMod({
+ include: "*",
+ contentScriptFile: data.url('dotjs.js'),
+ onAttach: function (worker) {
+ worker.port.on('init', function(domain) {
+ let host = url.URL(domain).host;
+ if (!host)
+ return;
- worker.on('message', function(msg) {
- var domain = url.URL(msg).host,
- dirSvc = Cc['@mozilla.org/file/directory_service;1']
- .getService(Ci.nsIProperties),
- homeDir = dirSvc.get('Home', Ci.nsIFile).path,
- jsDir = homeDir.indexOf('/') === 0 ? '.js' : 'js',
- cssDir = homeDir.indexOf('/') === 0 ? '.css' : 'css',
- files, filename;
- if (domain.indexOf('www.') === 0) {
- domain = domain.substring(4, domain.length);
+ if (host.indexOf('www.') === 0) {
+ host = host.substring(4, host.length);
}
+
+ let files = matchFile(host);
- files = ['default', domain];
- for (var i=0; i < files.length; i++) {
- filename = file.join(homeDir, jsDir, files[i]);
- if (file.exists(filename + '.js')) {
- worker.postMessage({
- js: file.read(filename + '.js')
- });
- }
- if (file.exists(filename + '.coffee')) {
- worker.postMessage({
- coffee: file.read(filename + '.coffee'),
- transpiler: data.load('coffee-script.js')
- });
- }
- cssname = file.join(homeDir, cssDir, files[i]);
- if (file.exists(cssname + '.css')) {
- worker.postMessage({
- css: file.read(cssname + '.css')
- });
- }
- }
+ // how to tell from here if we actually matched something?
+ if (files.match)
+ worker.port.emit('load-scripts', files);
});
- // later, add the worker as a property od the tab object, so we don't inject
- // the tab more than once.
- tab._dotjs_worker = worker;
}
});