# # Mozilla Extension Generator # Copyright 2007 Einar Egilsson # # See http://tech.einaregilsson.com/2007/08/01/mozilla-extension-generator/ for more info. # import os, sys, re, base64 #Constants #Fill these out so you won't get prompted for them everytime: YOUR_NAME = '' YOUR_DOMAIN = '' # if filled out the extension guid will be of the form extensionname@yourdomain.com FIREFOX_MIN = '2.0' FIREFOX_MAX = '2.0.0.*' THUNDERBIRD_MIN = '2.0' THUNDERBIRD_MAX = '2.0.0.*' INITIAL_VERSION = '0.9' def generate(): print 'Mozilla Extension Generator' print 'Copyright (c) 2007 Einar Egilsson (http://tech.einaregilsson.com)' print '' sections = {} exclude_sections = [] replacements = {} for keyword, prompt_text in repl_vars: replacements[keyword] = prompt(prompt_text) answer = '' while not answer.lower() in ['f', 't']: answer = prompt('Firefox or Thunderbird (f/t) ') sections['firefox'] = answer.lower() == 'f' sections['thunderbird'] = answer.lower() == 't' for keyword, prompt_text in section_vars: answer = '' while not answer.lower() in ['y', 'n']: answer = prompt('Include %s ? (y/n)' % prompt_text) sections[keyword] = answer.lower() == 'y' replacements['author'] = YOUR_NAME or prompt('Author name') extname = replacements['name'].lower() replacements['lname'] = extname replacements['lib'] = replacements['name'] + 'Lib' replacements['llib'] = replacements['lib'].lower() if YOUR_DOMAIN: replacements['guid'] = replacements['lname'] + '@' + YOUR_DOMAIN else: replacements['guid'] = prompt('Guid') replacements['fmin'] = FIREFOX_MIN replacements['fmax'] = FIREFOX_MAX replacements['tmin'] = THUNDERBIRD_MIN replacements['tmax'] = THUNDERBIRD_MAX replacements['version'] = INITIAL_VERSION if sections['menuitem']: replacements['menuName'] = prompt('Menu item label') replacements['menuAccessKey'] = prompt('Menu item access key') if sections['contextmenu']: replacements['contextName'] = prompt('Contextmenu item label') replacements['contextAccessKey'] = prompt('Contextmenu item access key') #Make all dirs needed os.makedirs(extname) for d in dirs: os.makedirs(os.path.join(extname, d)) print '\nCreating files...\n' #Proccess each file for filename, filecontent in files: is_img = filename[-3:] == 'png' #Include or exclude sections of code exclude_pattern = r'\[%s].*?\[/%s]\s*\n' include_pattern = r'\[/?%s]\s*\n' for key in sections: if sections[key]: pattern = include_pattern % key else: pattern = exclude_pattern % (key, key) regex = re.compile(pattern, re.DOTALL) filecontent = re.sub(regex, '', filecontent) #Simple keyword replacements filename = filename % replacements if not is_img: filecontent = filecontent % replacements filecontent = filecontent.strip() #The whole file might be wrapped in a section, and if the section #was removed we don't want to create the file if filecontent: if is_img: filecontent = base64.b64decode(filecontent) path = extname + '/' + filename file = open(path, 'wb') print path file.write(filecontent) file.flush() file.close() print '' print 'Extension complete' def prompt(prompt_text): sys.stdout.write(prompt_text + ': ') return raw_input() #Directories to create dirs = ['chrome/content', 'chrome/locale/en-US', 'chrome/skin', 'defaults/preferences'] repl_vars = ( ('prettyname', 'Extension name'), ('name', 'Extension code name'), ('descr', 'Extension description'), ) section_vars = ( ('menuitem', 'Menu item'), ('contextmenu', 'Context menu'), ) #Below here are only file templates files = ( ('install.rdf', """ %(guid)s %(prettyname)s %(version)s %(author)s %(descr)s chrome://%(lname)s/content/%(lname)s.png [firefox] {ec8030f7-c20a-464f-9b0e-13a3a9e97384} %(fmin)s %(fmax)s [/firefox] [thunderbird] {3550f703-e582-4d05-9a08-453d09bdfdc6} %(tmin)s %(tmax)s [/thunderbird] """), ('chrome.manifest', """ content %(lname)s file:chrome/content/ locale %(lname)s en-US file:chrome/locale/en-US/ skin %(lname)s classic/1.0 file:chrome/skin/ [thunderbird] overlay chrome://messenger/content/messenger.xul chrome://%(lname)s/content/overlay.xul [/thunderbird] [firefox] overlay chrome://browser/content/browser.xul chrome://%(lname)s/content/overlay.xul [/firefox] """), ('defaults/preferences/%(lname)s.js', """ pref("extensions.%(lname)s.debug", false); // See http://kb.mozillazine.org/Localize_extension_descriptions pref("extensions.%(guid)s.description", "chrome://%(lname)s/locale/%(lname)s.properties"); """), ('chrome/content/%(lname)s.js', """ var %(name)s = { id : "%(guid)s", name : "%(name)s", initialized : false, strings : null, onLoad : function(event) { try { // initialization code %(lib)s.initialize(this); [contextmenu] [thunderbird] $('threadPaneContext') [/thunderbird] [firefox] $('contentAreaContextMenu') [/firefox] .addEventListener("popupshowing", function(e) { %(name)s.showContextMenu(e); }, false); [/contextmenu] %(lib)s.debug("Initializing..."); this.strings = document.getElementById("%(lname)s-strings"); %(lib)s.debug("Finished initialization"); this.initialized = true; } catch(e) { //Don't use %(lib)s because it's initialization might have failed. if (this.strings) { alert(this.strings.getString("initError") .$ (this.name) + "\\n\\n" + e); } else { alert(e); } } }, onUnload : function(event) { //Clean up here %(lib)s.debug("Finished cleanup"); }, [contextmenu] showContextMenu : function(event) { [thunderbird] $("%(lname)s-context").hidden = (GetNumSelectedMessages() > 0); [/thunderbird] [firefox] $("%(lname)s-context").hidden = gContextMenu.onImage; [/firefox] }, onContextMenuCommand: function(event) { //Do your thing alert("Context menu command"); }, [/contextmenu] [menuitem] onMenuItemCommand: function(event) { alert("Menu item command"); }, [/menuitem] }; window.addEventListener("load", function(event) { %(name)s.onLoad(event); }, false); window.addEventListener("unload", function(event) { %(name)s.onUnload(event); }, false); """), ('chrome/content/overlay.xul', """