├── .gitignore ├── .zipignore ├── README.md ├── Rakefile ├── bootstrap.js ├── chrome.manifest ├── chrome ├── content │ ├── firefileModule.js │ ├── firefilePanel.js │ ├── lib │ │ ├── csssaver.js │ │ ├── csstransformer.js │ │ └── jquery.js │ └── main.js ├── locale │ ├── de-DE │ │ ├── firefile.dtd │ │ └── firefile.properties │ └── en-US │ │ ├── firefile.dtd │ │ └── firefile.properties └── skin │ ├── bg.png │ ├── firefile.css │ ├── firefile_32.png │ ├── firefile_autosave.png │ ├── firefile_autosave_disabled.png │ ├── firefile_cancel.png │ ├── firefile_cancel_hover.png │ ├── firefile_delete.png │ ├── firefile_delete_site.png │ ├── firefile_download.png │ ├── firefile_label_site.png │ ├── firefile_logout.png │ ├── firefile_nosave.png │ ├── firefile_save.png │ ├── firefile_save_active.png │ ├── firefile_save_error.png │ ├── firefile_save_hover.png │ ├── loading.gif │ ├── loading_grey.gif │ ├── skin.css │ ├── status_add.png │ ├── status_closed.png │ ├── status_disabled.png │ ├── status_open.png │ └── widgets.css ├── defaults └── preferences │ └── default.js ├── icons └── default │ └── firefile.ico └── install.rdf /.gitignore: -------------------------------------------------------------------------------- 1 | .DS_Store 2 | xpi/* 3 | -------------------------------------------------------------------------------- /.zipignore: -------------------------------------------------------------------------------- 1 | .git/* 2 | xpi/* 3 | .gitignore 4 | .zipignore 5 | .DS_Store 6 | */.DS_Store 7 | README.md 8 | Rakefile -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | ## [Install FireFile from firefile.at](http://www.firefile.at) 2 | ## [Install FireFile from Mozilla Addons](https://addons.mozilla.org/de/firefox/addon/firefile/) 3 | 4 | ## FireFile Firebug Extension 5 | 6 | Firefile is a Firebug extension that allows you to save the CSS files edited with firebug live to your web server by transfering it to a server- side script, which then handles css saving. 7 | FireFile remembers all modifications done to a website (all modified css files) and, by clicking on the lower- right FireFile icon, allows you to bulk save or download all changes made. 8 | 9 | ## INSTALLATION 10 | 11 | Download the latest version from github (Download- Button) in ".zip" file format, rename to ".xpi" and open with firefox 12 | 13 | ## FEATURES 14 | 15 | * Remote saving css changes 16 | * firefile.at webservice integration (see www.firefile.at) 17 | 18 | ## Version History 19 | 20 | * 0.9.2 (28.12.2012) 21 | ** Fixed bug that caused firefile not to register sites if the addon bar icon was not added 22 | ** Implemented FireFile Webservice feature 23 | 24 | * 0.9.1 (13.12.2012) 25 | ** Added compatibility for Firefox 17 (Firebug 1.11) 26 | ** Implemented AMD & bootstrapped architecture 27 | ** Fixed major issue with domplate interaction 28 | 29 | * 0.9.0 (14.01.2012) 30 | ** Added compatibility for Firefox 9.0.1 (Firebug 1.9.0) 31 | ** Added support for all style rule types (@fontface, @media, etc) 32 | ** Improved comment display and comment saving 33 | ** Improved css beautification 34 | ** Removed feature: css3 autoconversion to other browsers (scheduled for later release) 35 | 36 | * 0.8.8 (30.08.2011) 37 | ** Added compatibility for Firefox 6.0 (Firebug 1.8) - thanks to nightwing@github 38 | 39 | * 0.8.7 (15.04.2011) 40 | ** Added compatibility for Firefox 4.0 41 | 42 | * 0.8.6 (16.12.2010) 43 | ** feature: Added possibility to cancel changes in FireFile registered sites list (via "cancel" icon) 44 | ** feature: Added context menu option to cancel all changes made 45 | ** feature: Canceling changes also reloads the canceled css- files (and so resets the firebug changes) 46 | ** bugfix: !important declarations are no more ignored 47 | ** bugfix: FireFile changes get dismissed when context is destroyed (reload, close) 48 | ** meta: Updated Help Content (when no site is registered) 49 | 50 | * 0.8.5 (15.12.2010) 51 | ** First stable release 52 | -------------------------------------------------------------------------------- /Rakefile: -------------------------------------------------------------------------------- 1 | require 'pathname' 2 | require 'fileutils' 3 | 4 | version = %x[sed -n -e 's/\\(.*\\)<\\/em:version>/\\1/p' install.rdf].strip 5 | 6 | task :getversion do 7 | puts version 8 | end 9 | 10 | task :setversion, :version do |t, args| 11 | system("sed -i '' -E 's/(.*)<\\/em:version>/"+args.version+"<\\/em:version>/g' install.rdf") 12 | puts args.version 13 | end 14 | 15 | task :build do 16 | puts "Packaging FireFile #{version}" 17 | FileUtils.mkdir_p('xpi') 18 | FileUtils.rm_rf('xpi/firefile-#{version}.xpi') 19 | sh %{zip -r xpi/firefile-#{version}.xpi . -x@.zipignore} 20 | end 21 | 22 | task :createtag do 23 | sh %{git tag -a v#{version} -m "version #{version}"} 24 | end 25 | -------------------------------------------------------------------------------- /bootstrap.js: -------------------------------------------------------------------------------- 1 | /* See license.txt for terms of usage */ 2 | 3 | var {classes: Cc, interfaces: Ci, utils: Cu} = Components; 4 | 5 | Cu.import("resource://gre/modules/Services.jsm"); 6 | Cu.import("resource://gre/modules/AddonManager.jsm"); 7 | 8 | function install(data, reason) {} 9 | function uninstall(data, reason) {} 10 | function startup(data, reason) { firebugStartup(); } 11 | function shutdown(data, reason) { firebugShutdown(); } 12 | 13 | // ********************************************************************************************* // 14 | // Firebug Bootstrap API 15 | 16 | /** 17 | * Executed by Firebug framework when Firebug is started. Since the order of Firebug 18 | * and its bootstrapped extensions is not guaranteed this function is executed twice 19 | * (of course the registration happens just once): 20 | * 21 | * 1) When Firebug is loaded 22 | * 2) When this extension is loaded 23 | * 24 | * If Firebug is not loaded an exception happens 25 | */ 26 | function firebugStartup() 27 | { 28 | // var isFb = false; 29 | try { 30 | Cu.import("resource://firebug/loader.js"); 31 | FirebugLoader.registerBootstrapScope(this); 32 | } 33 | catch (e) { 34 | 35 | } 36 | 37 | } 38 | 39 | 40 | /** 41 | * Executed by Firefox when this extension shutdowns. 42 | */ 43 | function firebugShutdown() 44 | { 45 | try 46 | { 47 | Cu.import("resource://firebug/loader.js"); 48 | FirebugLoader.unregisterBootstrapScope(this); 49 | } 50 | catch (e) 51 | { 52 | Cu.reportError(e); 53 | } 54 | } 55 | 56 | // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // 57 | 58 | /** 59 | * Executed by Firebug framework for every browser window. Use this function to append 60 | * any new elements into the browser window (browser.xul). Don't forget to remove 61 | * these elements in topWindowUnload. 62 | * 63 | * @param {Window} win The browser window 64 | */ 65 | function topWindowLoad(win) 66 | { 67 | // Add navbar button 68 | var doc = win.document; 69 | var button = doc.createElement("toolbarbutton"); 70 | var firebugButtonId = "firebug-button"; 71 | var firefileButtonId = "firefile-button"; 72 | button.setAttribute("id", firefileButtonId); 73 | button.setAttribute("label", "FireFile"); 74 | button.setAttribute("class", "toolbarbutton-1 chromeclass-toolbar-additional"); 75 | button.style.listStyleImage = "url(chrome://FireFile/skin/status_disabled.png)"; 76 | button.setAttribute("tooltiptext", "FireFileToolTip"); 77 | button.addEventListener("command", function() { 78 | // Load Firebug and set FireFile Panel 79 | var requireScope = {}; 80 | Cu.import("resource://firebug/mini-require.js", requireScope); 81 | var require = requireScope.require; 82 | var config = { 83 | baseUrl: "resource://", 84 | paths: {"firebug": "chrome://firebug/content"} 85 | }; 86 | require(config, [ 87 | "firebug/lib/trace" 88 | ], function(FBTrace) { 89 | win.Firebug.browserOverlay.startFirebug(function() { 90 | win.Firebug.toggleBar(true); 91 | win.Firebug.FireFile.clickStatus(); 92 | }); 93 | }); 94 | }, false); 95 | restorePosition(win, button); 96 | var navBar = doc.getElementById("nav-bar"); 97 | if(navBar) { 98 | var currentSet = navBar.getAttribute("currentset").split(","); 99 | var exists = currentSet.indexOf(firefileButtonId); 100 | var atPosition = currentSet.indexOf(firebugButtonId) + 1; 101 | if(exists == -1) { 102 | currentSet.push(firefileButtonId); 103 | navBar.setAttribute("currentset", currentSet.join(",")); 104 | doc.persist(navBar.id, "currentset"); 105 | } 106 | } 107 | } 108 | 109 | function topWindowUnload(win) 110 | { 111 | // nothing to do here 112 | } 113 | 114 | function firebugFrameLoad(Firebug) 115 | { 116 | 117 | // Register trace prefix 118 | Firebug.registerTracePrefix("fireFile;", "DBG_FIREFILE", true); 119 | 120 | // Register firefile extension 121 | var config = {id: "firefile@strebitzer.at"}; 122 | Firebug.registerExtension("firefile", config); 123 | 124 | } 125 | 126 | function firebugFrameUnload(Firebug) 127 | { 128 | if (!Firebug.isInitialized) { 129 | return; 130 | } 131 | 132 | // Unregister firefile extension 133 | Firebug.unregisterExtension("firefile"); 134 | Firebug.unregisterTracePrefix("fireFile;"); 135 | } 136 | 137 | /** 138 | * Helper function to restore the addon- button in the toolbar 139 | * 140 | * @param {Window} win The browser window 141 | * @param button The button element 142 | */ 143 | restorePosition = function(win, button) { 144 | var doc = win.document; 145 | var toolbar; 146 | var currentset; 147 | var idx; 148 | var toolbars = doc.querySelectorAll("toolbar"); 149 | var toolbox = doc.getElementById("navigator-toolbox"); 150 | toolbox.palette.appendChild(button); 151 | for (let i = 0; i < toolbars.length; ++i) { 152 | var tb = toolbars[i]; 153 | currentset = tb.getAttribute("currentset").split(","), 154 | idx = currentset.indexOf(button.id); 155 | if (idx != -1) { 156 | toolbar = tb; 157 | break; 158 | } 159 | } 160 | 161 | if (!toolbar && (button.id in positions)) { 162 | var [tbID, beforeID] = positions[button.id]; 163 | toolbar = doc.getElementById(tbID); 164 | [currentset, idx] = persist(doc, toolbar, button.id, beforeID); 165 | } 166 | 167 | if (toolbar) { 168 | if (idx != -1) { 169 | for (let i = idx + 1; i < currentset.length; ++i) { 170 | let before = doc.getElementById(currentset[i]); 171 | if (before) { 172 | toolbar.insertItem(button.id, before); 173 | return; 174 | } 175 | } 176 | } 177 | toolbar.insertItem(button.id); 178 | } 179 | }; -------------------------------------------------------------------------------- /chrome.manifest: -------------------------------------------------------------------------------- 1 | content FireFile chrome/content/ contentaccessible=yes 2 | skin FireFile classic/1.0 chrome/skin/ 3 | locale FireFile en-US chrome/locale/en-US/ 4 | locale FireFile de-DE chrome/locale/de-DE/ 5 | # overlay chrome://firebug/content/firebugOverlay.xul chrome://FireFile/content/browser.xul 6 | # overlay chrome://browser/content/browser.xul chrome://FireFile/content/browserStatus.xul -------------------------------------------------------------------------------- /chrome/content/firefileModule.js: -------------------------------------------------------------------------------- 1 | /* See license.txt for terms of usage */ 2 | 3 | define([ 4 | "firebug/lib/object", 5 | "firebug/lib/trace", 6 | "firebug/lib/xpcom", 7 | "firebug/lib/dom", 8 | "firebug/lib/domplate", 9 | "firebug/lib/locale", 10 | "firebug/lib/events", 11 | "firefile/lib/csstransformer", 12 | "firefile/lib/csssaver" 13 | ], 14 | function(Obj, FBTrace, Xpcom, Dom, Domplate, Locale, Events, CssTransformer, CssSaver) { 15 | 16 | with (Domplate) { 17 | 18 | var Cc = Components.classes; 19 | var Ci = Components.interfaces; 20 | 21 | // Register FireFile string bundles. 22 | const categoryManager = Xpcom.CCSV("@mozilla.org/categorymanager;1", "nsICategoryManager"); 23 | const stringBundleService = Xpcom.CCSV("@mozilla.org/intl/stringbundle;1", "nsIStringBundleService"); 24 | const PromptService = Cc["@mozilla.org/embedcomp/prompt-service;1"].getService(Ci.nsIPromptService); 25 | const PrefBranch = Cc["@mozilla.org/preferences-service;1"].getService(Ci.nsIPrefBranch).getBranch("extensions.firefile."); 26 | 27 | var CSSDomplateBase = { 28 | isEditable: function(rule) 29 | { 30 | return !rule.isSystemSheet && !rule.isNotEditable; 31 | }, 32 | isSelectorEditable: function(rule) 33 | { 34 | return rule.isSelectorEditable && this.isEditable(rule); 35 | }, 36 | getPropertyValue: function(prop) 37 | { 38 | // Disabled, see http://code.google.com/p/fbug/issues/detail?id=5880 39 | /* 40 | var limit = Options.get("stringCropLength"); 41 | */ 42 | var limit = 0; 43 | if (limit > 0) 44 | return Str.cropString(prop.value, limit); 45 | return prop.value; 46 | }, 47 | getComments: function(object) { 48 | if(!Firebug.FireFile.prefs.display_comments) { 49 | return []; 50 | } 51 | 52 | var result = CssTransformer.getCommentForRule(object.rule); 53 | if(result !== false) { 54 | return result.split("\n"); 55 | } 56 | return []; 57 | }, 58 | getPropertyTextComments: function(object) { 59 | if(!Firebug.FireFile.prefs.display_comments) { 60 | return []; 61 | } 62 | 63 | // For now, return empty array 64 | return []; 65 | 66 | var result = CssTransformer.getPropertyCommentsForRule(object); 67 | if(result !== false) { 68 | return result; 69 | } 70 | return []; 71 | } 72 | }; 73 | 74 | var CSSPropTag = domplate(CSSDomplateBase, { 75 | tag: DIV({class: "cssProp focusRow", $disabledStyle: "$prop.disabled", 76 | $editGroup: "$rule|isEditable", 77 | $cssOverridden: "$prop.overridden", 78 | role: "option"}, 79 | 80 | // Use spaces for indent to make "copy to clipboard" nice. 81 | SPAN("    "), 82 | SPAN({class: "cssPropName", $editable: "$rule|isEditable"}, 83 | "$prop.name" 84 | ), 85 | 86 | // Use a space here, so that "copy to clipboard" has it (issue 3266). 87 | SPAN({class: "cssColon"}, ": "), 88 | SPAN({class: "cssPropValue", $editable: "$rule|isEditable", 89 | _repObject: "$prop.value$prop.important"}, "$prop|getPropertyValue$prop.important" 90 | ), 91 | SPAN({class: "cssSemi"}, ";") 92 | ) 93 | }); 94 | 95 | var CSSPropCommentTag = domplate(CSSDomplateBase, { 96 | tag: DIV({class: "cssProp focusRow propComment"}, 97 | SPAN("    /* $comment */") 98 | ) 99 | }); 100 | 101 | var CSSRuleTag = TAG("$rule.tag", {rule: "$rule"}); 102 | 103 | var CSSImportRuleTag = domplate({ 104 | tag: DIV({class: "cssRule insertInto focusRow importRule", _repObject: "$rule.rule"}, 105 | "@import "", 106 | A({class: "objectLink", _repObject: "$rule.rule.styleSheet"}, "$rule.rule.href"), 107 | "";" 108 | ) 109 | }); 110 | 111 | var CSSStyleRuleTag = domplate(CSSDomplateBase, 112 | { 113 | tag: 114 | DIV({class: "cssRule insertInto", 115 | $cssEditableRule: "$rule|isEditable", 116 | $insertInto: "$rule|isEditable", 117 | $editGroup: "$rule|isSelectorEditable", 118 | _repObject: "$rule.rule", 119 | role: "presentation"}, 120 | DIV({class: "ruleComment", title: "Comment"}, 121 | FOR("comment", "$rule|getComments", 122 | DIV({class: "ruleCommentLine"}, "$comment") 123 | ) 124 | ), 125 | DIV({class: "cssHead focusRow", role : 'listitem'}, 126 | SPAN({class: "cssSelector", $editable: "$rule|isSelectorEditable"}, 127 | "$rule.selector"), 128 | " {" 129 | ), 130 | DIV({role : 'group'}, 131 | DIV({"class" : "cssPropertyListBox", _rule: "$rule", role : 'listbox'}, 132 | FOR("comment", "$rule|getPropertyTextComments", 133 | TAG(CSSPropCommentTag.tag, {rule: "$rule", comment: "$comment"}) 134 | ), 135 | FOR("prop", "$rule.props", 136 | TAG(CSSPropTag.tag, {rule: "$rule", prop: "$prop"}) 137 | ) 138 | ) 139 | ), 140 | DIV({$editable: "$rule|isEditable", $insertBefore: "$rule|isEditable", 141 | role:"presentation"}, 142 | "}" 143 | ) 144 | ) 145 | }); 146 | 147 | var FireFileStyleDomPlate = domplate({ 148 | cascadedTag: 149 | DIV({class: "a11yCSSView", role: 'presentation'}, 150 | DIV({class: "cssNonInherited", role: "list", 151 | "aria-label" : Locale.$STR("aria.labels.style rules") }, 152 | FOR("rule", "$rules", 153 | TAG("$ruleTag", {rule: "$rule"}) 154 | ) 155 | ), 156 | DIV({role: "list", 'aria-label' :Locale.$STR('aria.labels.inherited style rules')}, 157 | FOR("section", "$inherited", 158 | H1({class: "cssInheritHeader groupHeader focusRow", role: 'listitem' }, 159 | SPAN({class: "cssInheritLabel"}, "$inheritLabel"), 160 | TAG(FirebugReps.Element.shortTag, {object: "$section.element"}) 161 | ), 162 | DIV({role: "group"}, 163 | FOR("rule", "$section.rules", 164 | TAG("$ruleTag", {rule: "$rule"}) 165 | ) 166 | ) 167 | ) 168 | ) 169 | ), 170 | 171 | ruleTag: 172 | DIV({class: "cssElementRuleContainer"}, 173 | TAG(CSSStyleRuleTag.tag, {rule: "$rule"}), 174 | DIV({class: "cssSourceLinkContainer FireFileChangeHook", styleurl: "$rule|getHref"}, 175 | DIV({class: "$rule|isTouched", onclick: "$saveChange", title: Locale.$STR("ClickToSaveChanges", "strings_firefile")}), 176 | TAG(FirebugReps.SourceLink.tag, {object: "$rule.sourceLink"}) 177 | ) 178 | ), 179 | 180 | newRuleTag: 181 | DIV({class: "cssElementRuleContainer"}, 182 | DIV({class: "cssRule insertBefore", style: "display: none"}, "") 183 | ), 184 | 185 | CSSFontPropValueTag: 186 | SPAN({class: "cssFontPropValue"}, 187 | FOR("part", "$propValueParts", 188 | SPAN({class: "$part.type|getClass", _repObject: "$part.font"}, "$part.value"), 189 | SPAN({class: "cssFontPropSeparator"}, "$part|getSeparator") 190 | ) 191 | ), 192 | getSeparator: function(part) 193 | { 194 | if (part.lastFont || part.type == "important") 195 | return ""; 196 | 197 | if (part.type == "otherProps") 198 | return " "; 199 | 200 | return ","; 201 | }, 202 | 203 | getClass: function(type) 204 | { 205 | switch (type) 206 | { 207 | case "used": 208 | return "cssPropValueUsed"; 209 | 210 | case "unused": 211 | return "cssPropValueUnused"; 212 | 213 | default: 214 | return ""; 215 | } 216 | }, 217 | 218 | getHref: function(rule) { 219 | try{ 220 | return rule.rule.parentStyleSheet.href; 221 | }catch(ex) { 222 | return ""; 223 | } 224 | }, 225 | isTouched: function(rule) { 226 | var parentSheet = rule.rule.parentStyleSheet; 227 | 228 | // Return inline styles 229 | if(parentSheet == undefined) {return "";} 230 | 231 | if(Firebug.FireFile.styleSheetExists(parentSheet.href)) { 232 | if(Firebug.FireFile.getHrefInAllowedSites(parentSheet.href)) { 233 | var classes = []; 234 | classes.push("fireFileSaveIcon"); 235 | if(Firebug.FireFile.styleSheetStatus[parentSheet.href] != undefined) { 236 | classes.push(Firebug.FireFile.styleSheetStatus[parentSheet.href]); 237 | } 238 | return classes.join(" "); 239 | } 240 | } 241 | return ""; 242 | }, 243 | saveChange: function(e) { 244 | var node = Dom.getAncestorByClass(e.target, "FireFileChangeHook"); 245 | var href = node.getAttribute('styleurl'); 246 | CssSaver.save(href); 247 | }, 248 | isFireFile: true 249 | }); 250 | 251 | Firebug.FireFile = Obj.extend(Firebug.Module, { 252 | 253 | // NOTIFICATIONS 254 | notifyCount: 0, 255 | errorCount: 0, 256 | 257 | // FIREFILE RUNTIME 258 | ffEnabled: false, 259 | htmlEnabled: false, 260 | currentURI: "", 261 | 262 | prefs: { 263 | enable_notifications: false, 264 | inspector_switch_css: true, 265 | display_comments: true, 266 | compress_css: false, 267 | enable_debug_mode: false 268 | }, 269 | 270 | // TIMEOUT HANDLING 271 | cssPreviousValue: "", 272 | cssEditing: false, 273 | 274 | destroyContext: function(context, persistedState) { 275 | 276 | var stylesheets = context.window.document.styleSheets; 277 | 278 | // Loop through all stylesheets 279 | for(var i=0;i=0;i--) { 299 | 300 | var href = Firebug.FireFile.modifiedStylesheets[i].href; 301 | 302 | // Destroy the changes (FireFile) 303 | Firebug.FireFile.destroyChanges(href); 304 | 305 | // Reset the changes (Firebug) 306 | Firebug.FireFile.resetStylesheet(href); 307 | 308 | // Reload Panel 309 | Firebug.currentContext.getPanel("firefile").select(); 310 | } 311 | }, 312 | resetStylesheet: function(href) { 313 | try{ 314 | var stylesheets = Firebug.currentContext.window.document.styleSheets; 315 | // Loop through all stylesheets 316 | for(var i=0;i=0;i--) { 763 | var existing_site = Firebug.FireFile.getHrefInAllowedSites(Firebug.FireFile.modifiedStylesheets[i].href); 764 | if(existing_site && existing_site.autosave) { 765 | CssSaver.save(Firebug.FireFile.modifiedStylesheets[i].href); 766 | } 767 | } 768 | } 769 | }, 770 | saveAllChanges: function() { 771 | // SAVE UNSAVED CHANGES 772 | for(var i=Firebug.FireFile.modifiedStylesheets.length-1;i>=0;i--) { 773 | var existing_site = Firebug.FireFile.getHrefInAllowedSites(Firebug.FireFile.modifiedStylesheets[i].href); 774 | if(existing_site) { 775 | CssSaver.save(Firebug.FireFile.modifiedStylesheets[i].href); 776 | } 777 | } 778 | }, 779 | styleSheetExists: function(value) { 780 | for (var i = 0; i < this.modifiedStylesheets.length; i++) { 781 | if (this.modifiedStylesheets[i].href == value) { 782 | return true; 783 | } 784 | } 785 | return false; 786 | }, 787 | styleSheetIndexByHref: function(value) { 788 | for (var i = 0; i < this.modifiedStylesheets.length; i++) { 789 | if (this.modifiedStylesheets[i].href == value) { 790 | return i; 791 | } 792 | } 793 | return false; 794 | }, 795 | clickStatus: function() { 796 | 797 | // OPEN SITES PANEL 798 | top.Firebug.chrome.selectPanel("html"); 799 | top.Firebug.chrome.selectSidePanel("firefile"); 800 | Firebug.currentContext.getPanel("firefile").select(); 801 | }, 802 | __: function(text) { 803 | try{ 804 | if (Firebug.FireFile.stringBundle == undefined) { 805 | categoryManager.addCategoryEntry("strings_firefile", "chrome://FireFile/locale/firefile.properties", "", false, true); 806 | Firebug.FireFile.stringBundle = stringBundleService.createExtensibleBundle("strings_firefile"); 807 | } 808 | text = Firebug.FireFile.stringBundle.GetStringFromName(text); 809 | 810 | // REPLACE PLACEHOLDERS 811 | if(arguments.length > 1) { 812 | for(var i=1;i 0) { 931 | this.notifyCount = change; 932 | notifyBox.appendNotification( 933 | "", 934 | barid, 935 | "chrome://firefile/skin/firefile_32.png", 936 | priority, 937 | Array( 938 | {label: Firebug.FireFile.__("NeverShow"), callback: this.onDisableNotify, popup: null} 939 | ) 940 | ); 941 | }else{ 942 | return false; 943 | } 944 | }else{ 945 | this.notifyCount += change; 946 | } 947 | 948 | // CHECK IF COUNT SMALLER OR EQUAL ZERO 949 | if(this.notifyCount <= 0) { 950 | // REMOVE ELEMENT 951 | this.notifyCount = 0; 952 | notifyBox.removeNotification(notifyBox.getNotificationWithValue(barid)); 953 | }else{ 954 | // UPDATE LABEL 955 | var label = ""; 956 | if(msgOnly) { 957 | label += Firebug.FireFile.__(msg); 958 | }else{ 959 | label += this.notifyCount+" "+Firebug.FireFile.__(msg); 960 | } 961 | 962 | notifyBox.getNotificationWithValue(barid).label = label; 963 | } 964 | }, 965 | onDisableNotify: function() { 966 | Firebug.FireFile.prefs.enable_notifications = false; 967 | 968 | var notifyBox = top.gBrowser.getNotificationBox(); 969 | if(notifyBox.getNotificationWithValue("ffnotify") != null) { 970 | notifyBox.removeNotification(notifyBox.getNotificationWithValue("ffnotify")); 971 | } 972 | if(notifyBox.getNotificationWithValue("fferror") != null) { 973 | notifyBox.removeNotification(notifyBox.getNotificationWithValue("fferror")); 974 | } 975 | }, 976 | togglePref: function(name, callback){ 977 | Firebug.setPref("extensions.firefile", name, !this.prefs[name]); 978 | this.prefs[name] = !this.prefs[name]; 979 | if(callback != undefined) { 980 | callback.call(this); 981 | } 982 | }, 983 | restartFirebug: function(on) 984 | { 985 | 986 | Components.utils.import("resource://gre/modules/Services.jsm"); 987 | Services.obs.notifyObservers(null, "startupcache-invalidate", null); 988 | 989 | var BOOTSTRAP_REASONS = { 990 | APP_STARTUP : 1, 991 | APP_SHUTDOWN : 2, 992 | ADDON_ENABLE : 3, 993 | ADDON_DISABLE : 4, 994 | ADDON_INSTALL : 5, 995 | ADDON_UNINSTALL : 6, 996 | ADDON_UPGRADE : 7, 997 | ADDON_DOWNGRADE : 8 998 | }; 999 | var XPIProviderBP = Components.utils.import("resource://gre/modules/XPIProvider.jsm"); 1000 | var id = "firebug@software.joehewitt.com"; 1001 | var XPIProvider = XPIProviderBP.XPIProvider; 1002 | var file = Cc["@mozilla.org/file/local;1"].createInstance(Ci.nsIFile); 1003 | file.persistentDescriptor = XPIProvider.bootstrappedAddons[id].descriptor; 1004 | 1005 | var t1 = Date.now(); 1006 | XPIProvider.callBootstrapMethod(id, XPIProvider.bootstrappedAddons[id].version, 1007 | XPIProvider.bootstrappedAddons[id].type, file, 1008 | "shutdown", BOOTSTRAP_REASONS.ADDON_DISABLE); 1009 | FBTrace.sysout("shutdown time :" + (Date.now() - t1) + "ms"); 1010 | if (!on) 1011 | return; 1012 | 1013 | t1 = Date.now() 1014 | XPIProvider.callBootstrapMethod(id, XPIProvider.bootstrappedAddons[id].version, 1015 | XPIProvider.bootstrappedAddons[id].type, file, 1016 | "startup", BOOTSTRAP_REASONS.APP_STARTUP); 1017 | FBTrace.sysout("startup time :" + (Date.now() - t1) + "ms"); 1018 | }, 1019 | addDebugInfo: function(title, data) { 1020 | if(Firebug.FireFile.prefs.enable_debug_mode) { 1021 | Firebug.Console.log(title); 1022 | for(var key in data) { 1023 | Firebug.Console.log([key+":", data[key]]); 1024 | } 1025 | } 1026 | } 1027 | }); 1028 | 1029 | return Firebug.FireFile; 1030 | 1031 | }}); -------------------------------------------------------------------------------- /chrome/content/firefilePanel.js: -------------------------------------------------------------------------------- 1 | /* See license.txt for terms of usage */ 2 | 3 | define([ 4 | "firebug/lib/object", 5 | "firebug/lib/trace", 6 | "firebug/lib/xpcom", 7 | "firebug/lib/dom", 8 | "firebug/lib/domplate", 9 | "firebug/lib/locale", 10 | "firefile/lib/jquery", 11 | "firefile/lib/csssaver" 12 | ], 13 | function(Obj, FBTrace, Xpcom, Dom, Domplate, Locale, $, CssSaver) { 14 | 15 | with (Domplate) { 16 | 17 | /* CHANGE PANEL */ 18 | const PromptService = Components.classes["@mozilla.org/embedcomp/prompt-service;1"].getService(Components.interfaces.nsIPromptService); 19 | const FireFilePrefDomain = "extensions.firefile"; 20 | 21 | var CSSDomplateBase = { 22 | isEditable: function(rule) 23 | { 24 | return !rule.isSystemSheet; 25 | }, 26 | isSelectorEditable: function(rule) 27 | { 28 | return rule.isSelectorEditable && this.isEditable(rule); 29 | } 30 | }; 31 | 32 | var FireFileChangesTags = domplate({ 33 | styleSheetTag: 34 | DIV({class: "cssChangesTopContainer"}, 35 | DIV({class: "cssChangesContainer FireFileChangeHook", styleurl: "$rule.href"}, 36 | SPAN({class: "fireFileCancelIcon", onclick: "$cancelChange", title: Locale.$STR("ClickToCancelChanges", "strings_firefile")}), 37 | SPAN({class: "$rule|isTouched", onclick: "$saveChange", title: Locale.$STR("ClickToSaveChanges", "strings_firefile")}), 38 | TAG(FirebugReps.SourceLink.tag, {object: "$rule"}), 39 | SPAN({class: "cssChangesPath"}, 40 | "$rule.href" 41 | ) 42 | ) 43 | ), 44 | getHref: function(rule) { 45 | try{ 46 | return rule.rule.parentStyleSheet.href; 47 | }catch(ex) { 48 | return ""; 49 | } 50 | }, 51 | isTouched: function(rule) { 52 | try{ 53 | var parentSheet = rule; 54 | if(Firebug.FireFile.styleSheetExists(parentSheet.href)) { 55 | var classes = []; 56 | classes.push("fireFileSaveIcon"); 57 | if(Firebug.FireFile.styleSheetStatus[parentSheet.href] != undefined) { 58 | classes.push(Firebug.FireFile.styleSheetStatus[parentSheet.href]); 59 | } 60 | return classes.join(" "); 61 | }else{ 62 | return ""; 63 | } 64 | }catch(ex) { 65 | return ""; 66 | } 67 | }, 68 | saveChange: function(e) { 69 | var node = Dom.getAncestorByClass(e.target, "FireFileChangeHook"); 70 | var href = node.getAttribute('styleurl'); 71 | CssSaver.save(href); 72 | }, 73 | cancelChange: function(e) { 74 | var node = Dom.getAncestorByClass(e.target, "FireFileChangeHook"); 75 | var href = node.getAttribute('styleurl'); 76 | 77 | // Destroy the changes (FireFile) 78 | Firebug.FireFile.destroyChanges(href); 79 | 80 | // Reset the changes (Firebug) 81 | Firebug.FireFile.resetStylesheet(href); 82 | 83 | // Reload Panel 84 | Firebug.currentContext.getPanel("firefile").select(); 85 | } 86 | }); 87 | 88 | function FireFilePanel() {} 89 | 90 | FireFilePanel.prototype = Obj.extend(Firebug.Panel, { 91 | template: domplate({ 92 | firefilePanelLoggedIn: 93 | DIV({id: "cssFireFilePanel", role: 'presentation'}, 94 | TAG("$changesListPanel", {sites: "$sites"}), 95 | TAG("$accountPanelLoggedIn") 96 | ), 97 | 98 | firefilePanelLoggedOut: 99 | DIV({id: "cssFireFilePanel", role: 'presentation'}, 100 | TAG("$changesListPanel", {sites: "$sites"}), 101 | TAG("$accountPanelLoggedOut"), 102 | TAG("$accountPanel") 103 | ), 104 | 105 | accountPanelLoggedIn: 106 | H1({style: "overflow: hidden;", class: "groupHeader cssFireFileHeaderSlim"}, 107 | DIV({class: "cssFireFileHostLabel", style: "width: 2000px; float: left; display: inline;"}, 108 | "$this|getUsername@firefile.at", 109 | SPAN({class: "cssFireFileHostLabel"}, 110 | A({"href": "http://www.firefile.at/stylesheets", target: "_blank"}, "Edit Settings") 111 | ) 112 | ), 113 | DIV({class: "cssFireFileSiteIconContainer"}, 114 | SPAN({class: "cssFireFileSiteIcon cssFireFileLogout", "title": Locale.$STR("Logout", "strings_firefile"), onclick: "$onLogoutClick"}) 115 | ) 116 | ), 117 | 118 | accountPanelLoggedOut: 119 | H1({style: "overflow: hidden;", class: "groupHeader cssFireFileHeaderSlim"}, "FireFile Account"), 120 | 121 | accountPanel: 122 | DIV({id: "cssFireFileAccountPanel", class: "cssFireFileFlexBox", role: 'presentation'}, 123 | DIV({id: 'cssFireFileLoginBox', class: "cssFireFilePanelBox"}, 124 | DIV({class: "cssFireFilePanelBoxHeader"}, "Login to your account"), 125 | P({class: "form-row"}, 126 | LABEL({for: "FireFileInputUsername"}, "Username:"), " ", 127 | INPUT({id: "FireFileInputUsername", type: "text", class: "cssFireFileInputBox", placeholder: "Your username", value: "$this|getUsername"}) 128 | ), 129 | P({class: "form-row"}, 130 | LABEL({for: "FireFileInputPassword"}, "Password:"), " ", 131 | INPUT({id: "FireFileInputPassword", type: "password", class: "cssFireFileInputBox"}) 132 | ), 133 | P({class: "form-row"}, 134 | LABEL(""), 135 | INPUT({id: "FireFileInputSubmit", type: "submit", "onclick": "$onLoginClick", class: "cssFireFileInputButton", "value": "Login"}) 136 | ) 137 | ), 138 | DIV({id: 'cssFireFileRegisterBox', class: "cssFireFilePanelBox cssFireFilePanelBoxLast"}, 139 | DIV({class: "cssFireFilePanelBoxHeader"}, "Create a new account"), 140 | P({class: "form-row"}, 141 | IMG({src: "chrome://FireFile/skin/firefile_32.png"}) 142 | ), 143 | P({class: "form-row"}, 144 | INPUT({type: "button", "onclick": "$onRegisterClick", class: "cssFireFileInputButton", "value": "Register now"}) 145 | ) 146 | ) 147 | /*, 148 | DIV({id: 'cssFireFileRegisterBox', class: "cssFireFilePanelBox cssFireFilePanelBoxLast"}, 149 | DIV({class: "cssFireFilePanelBoxHeader"}, "Create a new account"), 150 | P({class: "form-row"}, 151 | LABEL({for: "FireFileInputRegisterUsername"}, "Username:"), " ", 152 | INPUT({id: "FireFileInputRegisterUsername", type: "text", class: "cssFireFileInputBox", "placeholder": "Your username"}) 153 | ), 154 | P({class: "form-row"}, 155 | LABEL({for: "FireFileInputRegisterPassword"}, "Password:"), " ", 156 | INPUT({id: "FireFileInputRegisterPassword", type: "password", class: "cssFireFileInputBox"}) 157 | ), 158 | P({class: "form-row"}, 159 | LABEL({for: "FireFileInputRegisterPasswordRepeat"}, "Repeat:"), " ", 160 | INPUT({id: "FireFileInputRegisterPasswordRepeat", type: "password", class: "cssFireFileInputBox"}) 161 | ), 162 | P({class: "form-row"}, 163 | LABEL(""), 164 | INPUT({id: "FireFileInputRegisterSubmit", type: "submit", onclick: "$onRegisterClick", class: "cssFireFileInputButton", "value": "Register"}) 165 | ) 166 | )*/ 167 | ), 168 | changesListPanel: 169 | DIV({class: "cssFireFileSitesPanel", role: 'presentation'}, 170 | DIV({role : 'list', 'aria-label' : "firefile" }, 171 | FOR("site", "$sites", 172 | H1({style: "overflow: hidden;", class: "cssInheritHeader groupHeader focusRow FireFileSiteHook", role : 'listitem', siteurl: "$site.url"}, 173 | DIV({class: "cssFireFileHostLabel", style: "width: 2000px; float: left; display: inline;"}, 174 | "$site.label", 175 | SPAN({class: "cssFireFileHostLabel"}, 176 | A({"href": "$site.url", "target": "_blank"}, "$site.url|shortenUrl") 177 | ) 178 | ), 179 | DIV({class: "cssFireFileSiteIconContainer"}, 180 | SPAN({class: "cssFireFileSiteIcon cssFireFileHostDelete", "title": Locale.$STR("TrashIconTooltip", "strings_firefile"), onclick: "$onDeleteClick"}), 181 | SPAN({class: "cssFireFileSiteIcon cssFireFileHostEdit", "title": Locale.$STR("RenameIconTooltip", "strings_firefile"), onclick: "$onEditClick"}), 182 | SPAN({class: "cssFireFileSiteIcon cssFireFileHostAutoSave cssFireFileHostAutoSave$site.autosave|parseBool", "title": Locale.$STR("AutoSaveIconTooltip", "strings_firefile"), "onclick": "$onAutoSaveClick"}) 183 | ) 184 | ), 185 | DIV({role : 'group'}, 186 | FOR("change", "$site.changes|orEmpty", 187 | TAG(FireFileChangesTags.styleSheetTag, {rule: "$change"}) 188 | ) 189 | ) 190 | ) 191 | ) 192 | ), 193 | getUsername: function() { 194 | var username = Firebug.getPref("extensions.firefile", "username"); 195 | if(!username) { 196 | return ""; 197 | }else{ 198 | return username; 199 | } 200 | 201 | }, 202 | onLogoutClick: function(e) { 203 | 204 | Firebug.setPref("extensions.firefile", "token", ""); 205 | Firebug.currentContext.getPanel("firefile").select(); 206 | 207 | }, 208 | onLoginClick: function(e) { 209 | 210 | var doc = e.target.ownerDocument; 211 | var username = $(doc).find("#FireFileInputUsername").val(); 212 | var password = $(doc).find("#FireFileInputPassword").val(); 213 | 214 | $(doc).find("#FireFileInputSubmit").attr("disabled", "disabled"); 215 | 216 | Firebug.setPref("extensions.firefile", "username", username); 217 | 218 | $.ajax({ 219 | url: "http://www.firefile.at/api/login", 220 | dataType: 'json', 221 | type: 'POST', 222 | data: { 223 | username: username, 224 | password: password 225 | }, 226 | success: function(response) { 227 | if(response.success) { 228 | Firebug.setPref("extensions.firefile", "token", response.token); 229 | } 230 | $(doc).find("#FireFileInputSubmit").removeAttr("disabled"); 231 | Firebug.currentContext.getPanel("firefile").select(); 232 | }, 233 | error: function(response) { 234 | $(doc).find("#FireFileInputSubmit").removeAttr("disabled"); 235 | } 236 | }); 237 | }, 238 | onRestartClick: function(e) { 239 | Firebug.FireFile.restartFirebug(true); 240 | }, 241 | onRegisterClick: function(e) { 242 | top.gBrowser.selectedTab = top.gBrowser.addTab("http://www.firefile.at/register/"); 243 | }, 244 | orEmpty: function(data) { 245 | if(!data) { 246 | return []; 247 | }else{ 248 | return data; 249 | } 250 | }, 251 | shortenUrl: function(data) { 252 | if(data.length > 80) { 253 | return data.substr(0, 80) + "..."; 254 | }else{ 255 | return data; 256 | } 257 | }, 258 | parseBool: function(data) { 259 | if(data) { 260 | return "On"; 261 | }else{ 262 | return "Off"; 263 | } 264 | }, 265 | onEditClick: function(e) { 266 | 267 | var siteurl = Dom.getAncestorByClass(e.target, "FireFileSiteHook").getAttribute("siteurl"); 268 | var siteindex = Firebug.FireFile.getSiteIndexByUrl(siteurl); 269 | var check = {value: false}; 270 | var input = {value: Firebug.FireFile.sitesArray[siteindex].label}; 271 | var result = PromptService.prompt(null, Firebug.FireFile.__("ChangeLabel"), Firebug.FireFile.__("EnterNewLabel"), input, null, check); 272 | 273 | if(result && input.value != "") { 274 | if(!input.value.match(/[^a-zA-Z0-9-_\s\.\/]+/) && input.value.length <= 40) { 275 | Firebug.FireFile.sitesArray[siteindex].label = input.value; 276 | Firebug.FireFile.saveSitesArray(); 277 | Firebug.currentContext.getPanel("firefile").select(); 278 | }else{ 279 | Firebug.FireFile.updateNotify("fferror", 8, 1, "LabelError", true); 280 | } 281 | } 282 | 283 | }, 284 | onAutoSaveClick: function(e) { 285 | var siteurl = Dom.getAncestorByClass(e.target, "FireFileSiteHook").getAttribute("siteurl"); 286 | var siteindex = Firebug.FireFile.getSiteIndexByUrl(siteurl); 287 | Firebug.FireFile.sitesArray[siteindex].autosave = !Firebug.FireFile.sitesArray[siteindex].autosave; 288 | Firebug.FireFile.saveSitesArray(); 289 | Firebug.currentContext.getPanel("firefile").select(); 290 | }, 291 | onDeleteClick: function(e) { 292 | var siteurl = Dom.getAncestorByClass(e.target, "FireFileSiteHook").getAttribute("siteurl"); 293 | var siteindex = Firebug.FireFile.getSiteIndexByUrl(siteurl); 294 | var result = PromptService.confirm(null, Firebug.FireFile.__("DeleteSite"), Firebug.FireFile.__("ReallyDeleteSite", Firebug.FireFile.sitesArray[siteindex].label)); 295 | if(result === true) { 296 | 297 | // DELETE SITE 298 | Firebug.FireFile.sitesArray.splice(siteindex, 1); 299 | Firebug.FireFile.saveSitesArray(); 300 | 301 | // DELETE CHANGES 302 | for(var i=Firebug.FireFile.modifiedStylesheets.length-1;i>=0;i--) { 303 | if(Firebug.FireFile.getHrefInAllowedSites(Firebug.FireFile.modifiedStylesheets[i].href) === false) { 304 | Firebug.FireFile.modifiedStylesheets.splice(i, 1); 305 | } 306 | } 307 | 308 | Firebug.currentContext.getPanel("firefile").select(); 309 | } 310 | } 311 | }), 312 | select: function() { 313 | 314 | // LOAD FULL SITES ARRAY AGAIN 315 | var sites = Firebug.FireFile.getSitesArray(); 316 | var changes = Firebug.FireFile.modifiedStylesheets; 317 | 318 | // PREPARE CHANGES IN SITES ARRAY 319 | for(var i=0;i 1 ? opt : {}; 367 | if (typeof options.indent === 'undefined') { 368 | options.indent = ' '; 369 | } 370 | if (typeof options.openbrace === 'string') { 371 | openbracesuffix = (options.openbrace === 'end-of-line'); 372 | } 373 | 374 | function isWhitespace(c) { 375 | return (c === ' ') || (c === '\n') || (c === '\t') || (c === '\r') || (c === '\f'); 376 | } 377 | 378 | function isQuote(c) { 379 | return (c === '\'') || (c === '"'); 380 | } 381 | 382 | // FIXME: handle Unicode characters 383 | function isName(c) { 384 | return (ch >= 'a' && ch <= 'z') || 385 | (ch >= 'A' && ch <= 'Z') || 386 | (ch >= '0' && ch <= '9') || 387 | '-_*.:#'.indexOf(c) >= 0; 388 | } 389 | 390 | function appendIndent() { 391 | var i; 392 | for (i = depth; i > 0; i -= 1) { 393 | formatted += options.indent; 394 | } 395 | } 396 | 397 | function openBlock() { 398 | formatted = trimRight(formatted); 399 | if (openbracesuffix) { 400 | formatted += ' {'; 401 | } else { 402 | formatted += '\n'; 403 | appendIndent(); 404 | formatted += '{'; 405 | } 406 | if (ch2 !== '\n') { 407 | formatted += '\n'; 408 | } 409 | depth += 1; 410 | } 411 | 412 | function closeBlock() { 413 | depth -= 1; 414 | formatted = trimRight(formatted); 415 | formatted += '\n'; 416 | appendIndent(); 417 | formatted += '}'; 418 | blocks.push(formatted); 419 | formatted = ''; 420 | } 421 | 422 | if (String.prototype.trimRight) { 423 | trimRight = function (s) { 424 | return s.trimRight(); 425 | }; 426 | } else { 427 | // old Internet Explorer 428 | trimRight = function (s) { 429 | return s.replace(/\s+$/, ''); 430 | }; 431 | } 432 | 433 | State = { 434 | Start: 0, 435 | AtRule: 1, 436 | Block: 2, 437 | Selector: 3, 438 | Ruleset: 4, 439 | Property: 5, 440 | Separator: 6, 441 | Expression: 7 442 | }; 443 | 444 | depth = 0; 445 | state = State.Start; 446 | comment = false; 447 | blocks = []; 448 | 449 | // We want to deal with LF (\n) only 450 | style = style.replace(/\r\n/g, '\n'); 451 | 452 | while (index < length) { 453 | ch = style.charAt(index); 454 | ch2 = style.charAt(index + 1); 455 | index += 1; 456 | 457 | // Inside a string literal? 458 | if (isQuote(quote)) { 459 | formatted += ch; 460 | if (ch === quote) { 461 | quote = null; 462 | } 463 | if (ch === '\\' && ch2 === quote) { 464 | // Don't treat escaped character as the closing quote 465 | formatted += ch2; 466 | index += 1; 467 | } 468 | continue; 469 | } 470 | 471 | // Starting a string literal? 472 | if (isQuote(ch)) { 473 | formatted += ch; 474 | quote = ch; 475 | continue; 476 | } 477 | 478 | // Comment 479 | if (comment) { 480 | formatted += ch; 481 | if (ch === '*' && ch2 === '/') { 482 | comment = false; 483 | formatted += ch2; 484 | index += 1; 485 | } 486 | continue; 487 | } else { 488 | if (ch === '/' && ch2 === '*') { 489 | comment = true; 490 | formatted += ch; 491 | formatted += ch2; 492 | index += 1; 493 | continue; 494 | } 495 | } 496 | 497 | if (state === State.Start) { 498 | 499 | // Copy white spaces and control characters 500 | if (ch <= ' ' || ch.charCodeAt(0) >= 128) { 501 | state = State.Start; 502 | formatted += ch; 503 | continue; 504 | } 505 | 506 | // Selector or at-rule 507 | if (isName(ch) || (ch === '@')) { 508 | 509 | // Clear trailing whitespaces and linefeeds. 510 | str = trimRight(formatted); 511 | 512 | if (str.length === 0) { 513 | // If we have empty string after removing all the trailing 514 | // spaces, that means we are right after a block. 515 | // Ensure a blank line as the separator. 516 | formatted = '\n\n'; 517 | } else { 518 | // After finishing a ruleset or directive statement, 519 | // there should be one blank line. 520 | if (str.charAt(str.length - 1) === '}' || 521 | str.charAt(str.length - 1) === ';') { 522 | 523 | formatted = str + '\n\n'; 524 | } else { 525 | // After block comment, keep all the linefeeds but 526 | // start from the first column (remove whitespaces prefix). 527 | while (true) { 528 | ch2 = formatted.charAt(formatted.length - 1); 529 | if (ch2 !== ' ' && ch2.charCodeAt(0) !== 9) { 530 | break; 531 | } 532 | formatted = formatted.substr(0, formatted.length - 1); 533 | } 534 | } 535 | } 536 | formatted += ch; 537 | state = (ch === '@') ? State.AtRule : State.Selector; 538 | continue; 539 | } 540 | } 541 | 542 | if (state === State.AtRule) { 543 | 544 | // ';' terminates a statement. 545 | if (ch === ';') { 546 | formatted += ch; 547 | state = State.Start; 548 | continue; 549 | } 550 | 551 | // '{' starts a block 552 | if (ch === '{') { 553 | openBlock(); 554 | state = State.Block; 555 | continue; 556 | } 557 | 558 | formatted += ch; 559 | continue; 560 | } 561 | 562 | if (state === State.Block) { 563 | 564 | // Selector 565 | if (isName(ch)) { 566 | 567 | // Clear trailing whitespaces and linefeeds. 568 | str = trimRight(formatted); 569 | 570 | if (str.length === 0) { 571 | // If we have empty string after removing all the trailing 572 | // spaces, that means we are right after a block. 573 | // Ensure a blank line as the separator. 574 | formatted = '\n\n'; 575 | } else { 576 | // Insert blank line if necessary. 577 | if (str.charAt(str.length - 1) === '}') { 578 | formatted = str + '\n\n'; 579 | } else { 580 | // After block comment, keep all the linefeeds but 581 | // start from the first column (remove whitespaces prefix). 582 | while (true) { 583 | ch2 = formatted.charAt(formatted.length - 1); 584 | if (ch2 !== ' ' && ch2.charCodeAt(0) !== 9) { 585 | break; 586 | } 587 | formatted = formatted.substr(0, formatted.length - 1); 588 | } 589 | } 590 | } 591 | 592 | appendIndent(); 593 | formatted += ch; 594 | state = State.Selector; 595 | continue; 596 | } 597 | 598 | // '}' resets the state. 599 | if (ch === '}') { 600 | closeBlock(); 601 | state = State.Start; 602 | continue; 603 | } 604 | 605 | formatted += ch; 606 | continue; 607 | } 608 | 609 | if (state === State.Selector) { 610 | 611 | // '{' starts the ruleset. 612 | if (ch === '{') { 613 | openBlock(); 614 | state = State.Ruleset; 615 | continue; 616 | } 617 | 618 | // '}' resets the state. 619 | if (ch === '}') { 620 | closeBlock(); 621 | state = State.Start; 622 | continue; 623 | } 624 | 625 | formatted += ch; 626 | continue; 627 | } 628 | 629 | if (state === State.Ruleset) { 630 | 631 | // '}' finishes the ruleset. 632 | if (ch === '}') { 633 | closeBlock(); 634 | state = State.Start; 635 | if (depth > 0) { 636 | state = State.Block; 637 | } 638 | continue; 639 | } 640 | 641 | // Make sure there is no blank line or trailing spaces inbetween 642 | if (ch === '\n') { 643 | formatted = trimRight(formatted); 644 | formatted += '\n'; 645 | continue; 646 | } 647 | 648 | // property name 649 | if (!isWhitespace(ch)) { 650 | formatted = trimRight(formatted); 651 | formatted += '\n'; 652 | appendIndent(); 653 | formatted += ch; 654 | state = State.Property; 655 | continue; 656 | } 657 | formatted += ch; 658 | continue; 659 | } 660 | 661 | if (state === State.Property) { 662 | 663 | // ':' concludes the property. 664 | if (ch === ':') { 665 | formatted = trimRight(formatted); 666 | formatted += ': '; 667 | state = State.Expression; 668 | if (isWhitespace(ch2)) { 669 | state = State.Separator; 670 | } 671 | continue; 672 | } 673 | 674 | // '}' finishes the ruleset. 675 | if (ch === '}') { 676 | closeBlock(); 677 | state = State.Start; 678 | if (depth > 0) { 679 | state = State.Block; 680 | } 681 | continue; 682 | } 683 | 684 | formatted += ch; 685 | continue; 686 | } 687 | 688 | if (state === State.Separator) { 689 | 690 | // Non-whitespace starts the expression. 691 | if (!isWhitespace(ch)) { 692 | formatted += ch; 693 | state = State.Expression; 694 | continue; 695 | } 696 | 697 | // Anticipate string literal. 698 | if (isQuote(ch2)) { 699 | state = State.Expression; 700 | } 701 | 702 | continue; 703 | } 704 | 705 | if (state === State.Expression) { 706 | 707 | // '}' finishes the ruleset. 708 | if (ch === '}') { 709 | closeBlock(); 710 | state = State.Start; 711 | if (depth > 0) { 712 | state = State.Block; 713 | } 714 | continue; 715 | } 716 | 717 | // ';' completes the declaration. 718 | if (ch === ';') { 719 | formatted = trimRight(formatted); 720 | formatted += ';\n'; 721 | state = State.Ruleset; 722 | continue; 723 | } 724 | 725 | formatted += ch; 726 | continue; 727 | } 728 | 729 | // The default action is to copy the character (to prevent 730 | // infinite loop). 731 | formatted += ch; 732 | } 733 | 734 | formatted = blocks.join('') + formatted; 735 | 736 | return formatted; 737 | } 738 | 739 | }; 740 | 741 | return CssTransformer; 742 | 743 | }}); 744 | -------------------------------------------------------------------------------- /chrome/content/main.js: -------------------------------------------------------------------------------- 1 | /* See license.txt for terms of usage */ 2 | 3 | define([ 4 | "firebug/lib/trace", 5 | "firefile/firefileModule", 6 | "firefile/firefilePanel" 7 | ], 8 | function(FBTrace, FirefileModule, FirefilePanel) { 9 | 10 | var FireFileApp = { 11 | 12 | initialize: function() { 13 | 14 | if (FBTrace.DBG_FIREFILE) { 15 | FBTrace.sysout("fireFile; FireFile extension initialize"); 16 | } 17 | 18 | Firebug.registerModule(FirefileModule); 19 | Firebug.registerPanel(FirefilePanel); 20 | 21 | Firebug.registerStylesheet("chrome://firefile/skin/skin.css"); 22 | Firebug.registerStylesheet("chrome://firefile/skin/widgets.css"); 23 | Firebug.registerStringBundle("chrome://firefile/locale/firefile.properties"); 24 | 25 | }, 26 | 27 | shutdown: function() { 28 | 29 | if (FBTrace.DBG_FIREFILE) { 30 | FBTrace.sysout("fireFile; FireFile extension shutdown"); 31 | } 32 | 33 | Firebug.unregisterModule(FirefileModule); 34 | Firebug.unregisterPanel(FirefilePanel); 35 | 36 | Firebug.unregisterStylesheet("chrome://firefile/skin/skin.css"); 37 | Firebug.unregisterStylesheet("chrome://firefile/skin/widgets.css"); 38 | Firebug.unregisterStringBundle("chrome://firefile/locale/firefile.properties"); 39 | 40 | } 41 | 42 | } 43 | 44 | return FireFileApp; 45 | 46 | }); 47 | -------------------------------------------------------------------------------- /chrome/locale/de-DE/firefile.dtd: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | -------------------------------------------------------------------------------- /chrome/locale/de-DE/firefile.properties: -------------------------------------------------------------------------------- 1 | FireFile=FireFile 2 | AddToFireFile=FireFile Seite gefunden 3 | DoYouWantToAddTheSite=FireFile hat eine freigegebene Seite gefunden. Möchten Sie die Seite $1 zur Liste hinzufügen? 4 | FilesSuccessfullySaved=Datei(en) wurden erfolgreich gespeichert 5 | FileSaveAsSuccess=Die Datei wurde erfolgreich lokal gespeichert 6 | SaveDialogStylesheet=Stylesheet 7 | SaveDialogTitle=Stylesheet speichern unter ... 8 | ServerError=Datei(en) konnten nicht gespeichert werden (Server- Fehler?) 9 | VersionError=Datei(en) nicht gespeichert, bitte aktualisieren Sie die Server- Komponente auf Version 0.5.3 10 | FileErrors=Datei(en) konnten nicht gespeichert werden (Schreibrechte?) 11 | FileDamaged=Datei(en) konnten nicht gespeichert werden (Datei beschädigt?) 12 | LabelError=Die Bezeichnung darf nur aus Buchstaben, Zahlen, Leerzeichen und einigen Sonderzeichen bestehen ("-", "_", ".", "/") und darf maximal 40 Zeichen lang sein. 13 | NeverShow=immer ausblenden 14 | NoChangesMade=Keine Änderungen vorhanden. 15 | DeleteSite=Seite löschen 16 | ReallyDeleteSite=Möchten Sie die Seite "$1" wirklich löschen? 17 | ChangeLabel=Bezeichnung ändern 18 | EnterNewLabel=Bitte geben Sie eine neue Bezeichnung für die Seite an 19 | FireFileHelpTitle=FireFile Schnellstart 20 | DemoAccountDescription=Lade die Server- Komponente herunter um FireFile auf deinem Server zu aktivieren 21 | DemoAccountTitle=Download Server- Komponente 22 | DemoAccountUrl=https://github.com/tobiasstrebitzer/FireFile-Server/zipball/master 23 | HelpDescription=Das Wiki liefert die alle Infos die du brauchst, um mit FireFile zu arbeiten 24 | HelpTitle=Wiki / Dokumentation 25 | HelpUrl=https://github.com/tobiasstrebitzer/FireFile/wiki 26 | UserGuideDescription=Die Screenshots auf der Mozilla Addon Seite bieten eine visuelle Anleitung, wie FireFile installiert wird 27 | UserGuideTitle=Screenshot- Anleitung 28 | UserGuideUrl=https://addons.mozilla.org/en-US/firefox/addon/52365/ 29 | CreateCssRule=CSS- Regel erstellen in %S: 30 | AutoSaveIconTooltip=Aktiviert die automatische Sicherung 31 | RenameIconTooltip=Diese Seite umbenennen 32 | TrashIconTooltip=Diese Seite löschen 33 | ClickToSaveChanges=Klicken Sie hier, um Änderungen in dieser CSS- Datei zu speichern 34 | save_all_changes=Alle Änderungen speichern 35 | save_all_changes_tooltip=Klicken Sie hier, um alle ungesicherten Änderungen zu übernehmen 36 | cancel_all_changes=Alle Änderungen verwerfen 37 | cancel_all_changes_tooltip=Klicken Sie hier, um alle ungesicherten Änderungen zu verwerfen 38 | enable_debug_mode=Debug- Ausgabe aktivieren 39 | enable_debug_mode_tooltip=Bei aktiviertem Debug- Modus werden Transferdaten in der Firebug- Konsole ausgegeben 40 | enable_notifications=Benachrichtigung aktivieren 41 | enable_notifications_tooltip=Regelt, ob die Benachrichtigungsbalken bei Erfolg und Fehlern eingeblendet werden sollen. 42 | inspector_switch_css=Zeige CSS beim Inspizieren 43 | inspector_switch_css_tooltip=Wenn aktiviert, schaltet das rechte Subpanel beim Inspizieren automatisch auf das CSS- Panel um 44 | compress_css=Komprimiere CSS 45 | compress_css_tooltip=Wenn aktiviert, werden die CSS- Regeln komprimiert gespeichert 46 | display_comments=Zeige/Speichere Kommentare 47 | display_comments_tooltip=Im CSS- Sidepanel werden Kommentare angezeigt und beim Speichern übernommen -------------------------------------------------------------------------------- /chrome/locale/en-US/firefile.dtd: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | -------------------------------------------------------------------------------- /chrome/locale/en-US/firefile.properties: -------------------------------------------------------------------------------- 1 | FireFile=FireFile 2 | AddToFireFile=FireFile Site found 3 | DoYouWantToAddTheSite=A FireFile- enabled website was found. Do you want to add $1 to your list of allowed sites? 4 | FilesSuccessfullySaved=file(s) were successfully saved 5 | FileSaveAsSuccess=The File was successfully saved to your hard disk 6 | SaveDialogStylesheet=Stylesheet 7 | SaveDialogTitle=Save stylesheet as ... 8 | ServerError=file(s) could not be saved (server error?) 9 | VersionError=file(s) not saved, please update the Server Component to version 0.5.3 10 | FileErrors=file(s) could not be saved (file permissions?) 11 | FileDamaged=file(s) could not be saved (file damaged?) 12 | LabelError=The label may only consist of letters, numbers, spaces and some special characters ("-", "_", ".", "/") and may not proceed the length of 40 characters. 13 | NeverShow=never show 14 | NoChangesMade=Currently no changes to save. 15 | DeleteSite=Delete site 16 | ReallyDeleteSite=Do you really want to delete "$1" 17 | ChangeLabel=Change site label 18 | EnterNewLabel=Please enter a new label for this site 19 | FireFileHelpTitle=FireFile Quick Start 20 | DemoAccountDescription=To start working with FireFile, download the server- component from here 21 | DemoAccountTitle=Download Server- Component 22 | DemoAccountUrl=https://github.com/tobiasstrebitzer/FireFile-Server/zipball/master 23 | HelpDescription=The wiki provides everything you need to know to get FireFile running 24 | HelpTitle=Wiki / Documentation 25 | HelpUrl=https://github.com/tobiasstrebitzer/FireFile/wiki 26 | UserGuideDescription=Follow the screenshots on the Mozilla Addon page for a visual Getting Started Guide 27 | UserGuideTitle=Screenshot Guide 28 | UserGuideUrl=https://addons.mozilla.org/en-US/firefox/addon/52365/ 29 | CreateCssRule=Create CSS Rule on %S: 30 | ClickToSaveChanges=Click here to save all changes to this stylesheet 31 | AutoSaveIconTooltip=Activate the autosave- feature for this site 32 | RenameIconTooltip=Rename this site 33 | TrashIconTooltip=Delete this site 34 | save_all_changes=Save all changes 35 | save_all_changes_tooltip=Click here to immediately save all unsaved changes 36 | cancel_all_changes=Cancel all changes 37 | cancel_all_changes_tooltip=Click here to immediately cancel all unsaved changes 38 | enable_debug_mode=Enable debug mode 39 | enable_debug_mode_tooltip=Activate the debug mode to log transfer data to the Firebug console. 40 | enable_notifications=Enable notifications 41 | enable_notifications_tooltip=Show/Hide the notification bar on transfer success and errors 42 | inspector_switch_css=Switch to CSS on inspect 43 | inspector_switch_css_tooltip=When active, the CSS subpanel is automatically activated when inspecting 44 | compress_css=Compress CSS 45 | compress_css_tooltip=When active, css styles are stored compressed 46 | display_comments=Display/Save CSS Comments 47 | display_comments_tooltip=When active, shows/saves CSS comments in the css sidepanel tab -------------------------------------------------------------------------------- /chrome/skin/bg.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tobiasstrebitzer/FireFile/0cc1cdd02884936a6738363a2d8974ad2007b952/chrome/skin/bg.png -------------------------------------------------------------------------------- /chrome/skin/firefile.css: -------------------------------------------------------------------------------- 1 | /* CSS PANEL */ 2 | div#ffCssPanelSaveButtonContainer span { 3 | background: transparent url(chrome://FireFile/skin/firefile_save.png) no-repeat 1px 1px; 4 | width: 16px; 5 | height: 16px; 6 | margin-right: 4px; 7 | } 8 | 9 | div#ffCssPanelSaveButtonContainer span:hover { 10 | background: transparent url(chrome://FireFile/skin/firefile_save_hover.png) no-repeat 1px 1px; 11 | } 12 | 13 | div#ffCssPanelSaveButtonContainer span:active { 14 | background: transparent url(chrome://FireFile/skin/firefile_save_active.png) no-repeat 1px 1px; 15 | } 16 | 17 | div#ffCssPanelSaveButtonContainer span.autosave { 18 | background: transparent url(chrome://FireFile/skin/firefile_autosave.png) no-repeat 1px 1px; 19 | } 20 | 21 | div#ffCssPanelSaveButtonContainer span.saving { 22 | background: transparent url(chrome://FireFile/skin/loading_grey.gif) no-repeat 1px 1px; 23 | } 24 | 25 | div#ffCssPanelSaveButtonContainer span.error { 26 | background: transparent url(chrome://FireFile/skin/firefile_error.png) no-repeat 1px 1px; 27 | } 28 | 29 | div#ffCssPanelSaveButtonContainer span.disabled { 30 | background: transparent url(chrome://FireFile/skin/firefile_nosave.png) no-repeat 1px 1px; 31 | width: 16px; 32 | height: 16px; 33 | margin-right: 4px; 34 | } 35 | 36 | 37 | /* MAIN PANEL */ 38 | div.cssFireFileSiteIconContainer { 39 | float: right; 40 | position: absolute; 41 | right: 0px; 42 | background: #EEEEEE; 43 | } 44 | 45 | span.cssFireFileSiteIcon { 46 | float: right; 47 | cursor: pointer; 48 | display: inline; 49 | width: 16px; 50 | height: 16px; 51 | margin: 0px 0px 0px 6px; 52 | } 53 | 54 | span.cssFireFileHostEdit { 55 | background: url(chrome://FireFile/skin/firefile_label_site.png); 56 | } 57 | 58 | span.cssFireFileHostDelete { 59 | background: url(chrome://FireFile/skin/firefile_delete_site.png); 60 | } 61 | 62 | span.cssFireFileHostAutoSaveOn { 63 | background: url(chrome://FireFile/skin/firefile_autosave.png); 64 | } 65 | 66 | span.cssFireFileHostAutoSaveOff { 67 | background: url(chrome://FireFile/skin/firefile_autosave_disabled.png); 68 | } 69 | 70 | /* HELP VIEW */ 71 | div.cssFireFileIntroduction { 72 | padding: 0px 0px 8px 8px; 73 | } 74 | 75 | /* CHANGES PANEL */ 76 | div.cssChangesTopContainer { 77 | overflow: hidden; 78 | } 79 | 80 | span.cssFireFileHostLabel { 81 | font-weight: normal; 82 | margin: 0px 0px 0px 4px; 83 | cursor: pointer; 84 | } 85 | 86 | span.cssFireFileHostLabel a { 87 | color: #999; 88 | } 89 | 90 | span.cssFireFileHostLabel a:hover { 91 | color: #00598E; 92 | text-decoration: underline; 93 | } 94 | 95 | div.cssChangesContainer { 96 | padding: 0px 4px 2px 4px; 97 | margin: 0px; 98 | height: 16px; 99 | font-family: Lucida Grande, sans-serif; 100 | font-weight: bold; 101 | border-bottom: 1px dotted #EEEEEE; 102 | width: 2000px; 103 | overflow: hidden; 104 | } 105 | 106 | 107 | div.cssChangesContainer a{ 108 | display: inline; 109 | float: left; 110 | margin: 0px 4px 0px 0px; 111 | } 112 | 113 | div.cssChangesContainer span.cssChangesPath { 114 | clip : auto; 115 | overflow: hidden; 116 | float: left; 117 | font-weight: normal; 118 | font-style: italic; 119 | color: #CCCCCC; 120 | } 121 | 122 | div.cssChangesContainer:hover span.cssChangesPath { 123 | color: #999999; 124 | } 125 | 126 | div.cssChangesContainer span.fireFileSaveIcon { 127 | background: url(chrome://FireFile/skin/firefile_save.png); 128 | float: left; 129 | cursor: pointer; 130 | display: inline; 131 | width: 16px; 132 | height: 16px; 133 | margin: 0px 4px 0px 0px !important; 134 | } 135 | 136 | div.cssChangesContainer span.fireFileCancelIcon:hover { 137 | background: url(chrome://FireFile/skin/firefile_cancel_hover.png); 138 | } 139 | 140 | div.cssChangesContainer span.fireFileCancelIcon { 141 | background: url(chrome://FireFile/skin/firefile_cancel.png); 142 | float: left; 143 | cursor: pointer; 144 | display: inline; 145 | width: 16px; 146 | height: 16px; 147 | margin: 0px 2px 0px 0px !important; 148 | } 149 | 150 | div.cssChangesContainer span.fireFileSaveIcon:hover { 151 | background: url(chrome://FireFile/skin/firefile_save_hover.png); 152 | } 153 | 154 | div.cssChangesContainer span.saving { 155 | background: url(chrome://FireFile/skin/loading.gif) !important; 156 | } 157 | 158 | div.cssChangesContainer span.error { 159 | background: url(chrome://FireFile/skin/firefile_save_error.png) !important; 160 | } 161 | 162 | /* HTML CSS PANEL HOOK'n'HACK */ 163 | a.objectLink-sourceLink { 164 | position: relative; 165 | top: 0; 166 | right: 0; 167 | margin: 0; 168 | padding: 0; 169 | } 170 | 171 | div.cssSourceLinkContainer { 172 | position: absolute; 173 | right: 4px; 174 | top: 2px; 175 | padding-left: 0px; 176 | font-family: Lucida Grande, sans-serif; 177 | font-weight: bold; 178 | color: #0000FF; 179 | } 180 | 181 | div.cssSourceLinkContainer div.fireFileSaveIcon { 182 | background: url(chrome://FireFile/skin/firefile_save.png); 183 | float: left; 184 | cursor: pointer; 185 | display: inline; 186 | margin: 0px 0px 0px -18px; 187 | width: 16px; 188 | height: 16px; 189 | } 190 | 191 | div.cssSourceLinkContainer div.fireFileSaveIcon:hover { 192 | background: url(chrome://FireFile/skin/firefile_save_hover.png); 193 | } 194 | 195 | div.cssSourceLinkContainer div.saving { 196 | background: url(chrome://FireFile/skin/loading.gif) !important; 197 | } 198 | 199 | div.cssSourceLinkContainer div.autosave { 200 | background: url(chrome://FireFile/skin/firefile_autosave.png) !important; 201 | } 202 | 203 | div.cssSourceLinkContainer div.error { 204 | background: url(chrome://FireFile/skin/firefile_save_error.png) !important; 205 | } 206 | 207 | div.ruleCommentLine, div.propComment span { 208 | color: #004AFF; 209 | } 210 | -------------------------------------------------------------------------------- /chrome/skin/firefile_32.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tobiasstrebitzer/FireFile/0cc1cdd02884936a6738363a2d8974ad2007b952/chrome/skin/firefile_32.png -------------------------------------------------------------------------------- /chrome/skin/firefile_autosave.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tobiasstrebitzer/FireFile/0cc1cdd02884936a6738363a2d8974ad2007b952/chrome/skin/firefile_autosave.png -------------------------------------------------------------------------------- /chrome/skin/firefile_autosave_disabled.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tobiasstrebitzer/FireFile/0cc1cdd02884936a6738363a2d8974ad2007b952/chrome/skin/firefile_autosave_disabled.png -------------------------------------------------------------------------------- /chrome/skin/firefile_cancel.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tobiasstrebitzer/FireFile/0cc1cdd02884936a6738363a2d8974ad2007b952/chrome/skin/firefile_cancel.png -------------------------------------------------------------------------------- /chrome/skin/firefile_cancel_hover.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tobiasstrebitzer/FireFile/0cc1cdd02884936a6738363a2d8974ad2007b952/chrome/skin/firefile_cancel_hover.png -------------------------------------------------------------------------------- /chrome/skin/firefile_delete.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tobiasstrebitzer/FireFile/0cc1cdd02884936a6738363a2d8974ad2007b952/chrome/skin/firefile_delete.png -------------------------------------------------------------------------------- /chrome/skin/firefile_delete_site.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tobiasstrebitzer/FireFile/0cc1cdd02884936a6738363a2d8974ad2007b952/chrome/skin/firefile_delete_site.png -------------------------------------------------------------------------------- /chrome/skin/firefile_download.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tobiasstrebitzer/FireFile/0cc1cdd02884936a6738363a2d8974ad2007b952/chrome/skin/firefile_download.png -------------------------------------------------------------------------------- /chrome/skin/firefile_label_site.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tobiasstrebitzer/FireFile/0cc1cdd02884936a6738363a2d8974ad2007b952/chrome/skin/firefile_label_site.png -------------------------------------------------------------------------------- /chrome/skin/firefile_logout.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tobiasstrebitzer/FireFile/0cc1cdd02884936a6738363a2d8974ad2007b952/chrome/skin/firefile_logout.png -------------------------------------------------------------------------------- /chrome/skin/firefile_nosave.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tobiasstrebitzer/FireFile/0cc1cdd02884936a6738363a2d8974ad2007b952/chrome/skin/firefile_nosave.png -------------------------------------------------------------------------------- /chrome/skin/firefile_save.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tobiasstrebitzer/FireFile/0cc1cdd02884936a6738363a2d8974ad2007b952/chrome/skin/firefile_save.png -------------------------------------------------------------------------------- /chrome/skin/firefile_save_active.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tobiasstrebitzer/FireFile/0cc1cdd02884936a6738363a2d8974ad2007b952/chrome/skin/firefile_save_active.png -------------------------------------------------------------------------------- /chrome/skin/firefile_save_error.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tobiasstrebitzer/FireFile/0cc1cdd02884936a6738363a2d8974ad2007b952/chrome/skin/firefile_save_error.png -------------------------------------------------------------------------------- /chrome/skin/firefile_save_hover.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tobiasstrebitzer/FireFile/0cc1cdd02884936a6738363a2d8974ad2007b952/chrome/skin/firefile_save_hover.png -------------------------------------------------------------------------------- /chrome/skin/loading.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tobiasstrebitzer/FireFile/0cc1cdd02884936a6738363a2d8974ad2007b952/chrome/skin/loading.gif -------------------------------------------------------------------------------- /chrome/skin/loading_grey.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tobiasstrebitzer/FireFile/0cc1cdd02884936a6738363a2d8974ad2007b952/chrome/skin/loading_grey.gif -------------------------------------------------------------------------------- /chrome/skin/skin.css: -------------------------------------------------------------------------------- 1 | /* WEBSERVICE */ 2 | 3 | div#cssFireFileAccountPanel { 4 | width: 100%; 5 | } 6 | 7 | input.cssFireFileInputBox { 8 | width: 100px; 9 | } 10 | 11 | input.cssFireFileInputButton { 12 | width: 108px; 13 | } 14 | 15 | div#cssFireFileAccountPanel p.form-row { 16 | position: relative; 17 | text-align: center; 18 | } 19 | 20 | /* PANEL BOX */ 21 | 22 | div.cssFireFilePanelBox { 23 | margin: 0px 0px 0px 4px; 24 | border: 1px solid #DDDDDD; 25 | } 26 | 27 | div.cssFireFilePanelBoxHeader { 28 | text-align: center; 29 | padding: 0px; 30 | margin: 0px; 31 | line-height: 16px; 32 | background: linear-gradient(#F5F5F5, #EEEEEE); 33 | border-bottom: 1px solid #CCCCCC; 34 | } 35 | 36 | /* FLEX BOX */ 37 | 38 | .cssFireFileFlexBox { 39 | display: -moz-box; 40 | -moz-box-orient: horizontal; 41 | -moz-box-align: stretch; 42 | } 43 | 44 | 45 | .cssFireFileFlexBox > * { 46 | -moz-box-flex: 1; 47 | display: block; 48 | } 49 | 50 | div.cssFireFilePanelBox.cssFireFilePanelBoxLast { 51 | margin-right: 4px; 52 | } 53 | 54 | 55 | div#cssFireFileAccountPanel label { 56 | width: 64px; 57 | display: inline-block; 58 | } 59 | 60 | /* CSS PANEL */ 61 | div#ffCssPanelSaveButtonContainer span { 62 | background: transparent url(chrome://FireFile/skin/firefile_save.png) no-repeat 1px 1px; 63 | width: 16px; 64 | height: 16px; 65 | margin-right: 4px; 66 | } 67 | 68 | div#ffCssPanelSaveButtonContainer span:hover { 69 | background: transparent url(chrome://FireFile/skin/firefile_save_hover.png) no-repeat 1px 1px; 70 | } 71 | 72 | div#ffCssPanelSaveButtonContainer span:active { 73 | background: transparent url(chrome://FireFile/skin/firefile_save_active.png) no-repeat 1px 1px; 74 | } 75 | 76 | div#ffCssPanelSaveButtonContainer span.autosave { 77 | background: transparent url(chrome://FireFile/skin/firefile_autosave.png) no-repeat 1px 1px; 78 | } 79 | 80 | div#ffCssPanelSaveButtonContainer span.saving { 81 | background: transparent url(chrome://FireFile/skin/loading_grey.gif) no-repeat 1px 1px; 82 | } 83 | 84 | div#ffCssPanelSaveButtonContainer span.error { 85 | background: transparent url(chrome://FireFile/skin/firefile_error.png) no-repeat 1px 1px; 86 | } 87 | 88 | div#ffCssPanelSaveButtonContainer span.disabled { 89 | background: transparent url(chrome://FireFile/skin/firefile_nosave.png) no-repeat 1px 1px; 90 | width: 16px; 91 | height: 16px; 92 | margin-right: 4px; 93 | } 94 | 95 | 96 | /* MAIN PANEL */ 97 | div.cssFireFileSiteIconContainer { 98 | float: right; 99 | position: absolute; 100 | right: 0px; 101 | } 102 | 103 | span.cssFireFileSiteIcon { 104 | float: right; 105 | cursor: pointer; 106 | display: inline; 107 | width: 16px; 108 | height: 16px; 109 | margin: 0px 0px 0px 6px; 110 | } 111 | 112 | span.cssFireFileHostEdit { 113 | background: url(chrome://FireFile/skin/firefile_label_site.png) no-repeat top left transparent; 114 | } 115 | 116 | span.cssFireFileLogout { 117 | background: url(chrome://FireFile/skin/firefile_logout.png) no-repeat top left transparent; 118 | } 119 | 120 | span.cssFireFileHostDelete { 121 | background: url(chrome://FireFile/skin/firefile_delete_site.png) no-repeat top left transparent; 122 | } 123 | 124 | span.cssFireFileHostAutoSaveOn { 125 | background: url(chrome://FireFile/skin/firefile_autosave.png) no-repeat top left transparent; 126 | } 127 | 128 | span.cssFireFileHostAutoSaveOff { 129 | background: url(chrome://FireFile/skin/firefile_autosave_disabled.png) no-repeat top left transparent; 130 | } 131 | 132 | /* HELP VIEW */ 133 | div.cssFireFileIntroduction { 134 | padding: 0px 0px 8px 8px; 135 | } 136 | 137 | /* CHANGES PANEL */ 138 | div.cssChangesTopContainer { 139 | overflow: hidden; 140 | } 141 | 142 | span.cssFireFileHostLabel { 143 | font-weight: normal; 144 | margin: 0px 0px 0px 4px; 145 | cursor: pointer; 146 | } 147 | 148 | span.cssFireFileHostLabel a { 149 | color: #999; 150 | } 151 | 152 | span.cssFireFileHostLabel a:hover { 153 | color: #00598E; 154 | text-decoration: underline; 155 | } 156 | 157 | div.cssChangesContainer { 158 | padding: 0px 4px 2px 4px; 159 | margin: 0px; 160 | height: 16px; 161 | font-family: Lucida Grande, sans-serif; 162 | font-weight: bold; 163 | border-bottom: 1px dotted #EEEEEE; 164 | width: 2000px; 165 | overflow: hidden; 166 | } 167 | 168 | 169 | div.cssChangesContainer a{ 170 | display: inline; 171 | float: left; 172 | margin: 0px 4px 0px 0px; 173 | } 174 | 175 | div.cssChangesContainer span.cssChangesPath { 176 | clip : auto; 177 | overflow: hidden; 178 | float: left; 179 | font-weight: normal; 180 | font-style: italic; 181 | color: #CCCCCC; 182 | } 183 | 184 | div.cssChangesContainer:hover span.cssChangesPath { 185 | color: #999999; 186 | } 187 | 188 | div.cssChangesContainer span.fireFileSaveIcon { 189 | background: url(chrome://FireFile/skin/firefile_save.png); 190 | float: left; 191 | cursor: pointer; 192 | display: inline; 193 | width: 16px; 194 | height: 16px; 195 | margin: 0px 4px 0px 0px !important; 196 | } 197 | 198 | div.cssChangesContainer span.fireFileCancelIcon:hover { 199 | background: url(chrome://FireFile/skin/firefile_cancel_hover.png); 200 | } 201 | 202 | div.cssChangesContainer span.fireFileCancelIcon { 203 | background: url(chrome://FireFile/skin/firefile_cancel.png); 204 | float: left; 205 | cursor: pointer; 206 | display: inline; 207 | width: 16px; 208 | height: 16px; 209 | margin: 0px 2px 0px 0px !important; 210 | } 211 | 212 | div.cssChangesContainer span.fireFileSaveIcon:hover { 213 | background: url(chrome://FireFile/skin/firefile_save_hover.png); 214 | } 215 | 216 | div.cssChangesContainer span.saving { 217 | background: url(chrome://FireFile/skin/loading.gif) !important; 218 | } 219 | 220 | div.cssChangesContainer span.error { 221 | background: url(chrome://FireFile/skin/firefile_save_error.png) !important; 222 | } 223 | 224 | /* HTML CSS PANEL HOOK'n'HACK */ 225 | a.objectLink-sourceLink { 226 | position: relative; 227 | top: 0; 228 | right: 0; 229 | margin: 0; 230 | padding: 0; 231 | } 232 | 233 | div.cssSourceLinkContainer { 234 | position: absolute; 235 | right: 4px; 236 | top: 2px; 237 | padding-left: 0px; 238 | font-family: Lucida Grande, sans-serif; 239 | font-weight: bold; 240 | color: #0000FF; 241 | } 242 | 243 | div.cssSourceLinkContainer div.fireFileSaveIcon { 244 | background: url(chrome://FireFile/skin/firefile_save.png); 245 | float: left; 246 | cursor: pointer; 247 | display: inline; 248 | margin: 0px 0px 0px -18px; 249 | width: 16px; 250 | height: 16px; 251 | } 252 | 253 | div.cssSourceLinkContainer div.fireFileSaveIcon:hover { 254 | background: url(chrome://FireFile/skin/firefile_save_hover.png); 255 | } 256 | 257 | div.cssSourceLinkContainer div.saving { 258 | background: url(chrome://FireFile/skin/loading.gif) !important; 259 | } 260 | 261 | div.cssSourceLinkContainer div.autosave { 262 | background: url(chrome://FireFile/skin/firefile_autosave.png) !important; 263 | } 264 | 265 | div.cssSourceLinkContainer div.error { 266 | background: url(chrome://FireFile/skin/firefile_save_error.png) !important; 267 | } 268 | 269 | div.ruleCommentLine, div.propComment span { 270 | color: #004AFF; 271 | } 272 | -------------------------------------------------------------------------------- /chrome/skin/status_add.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tobiasstrebitzer/FireFile/0cc1cdd02884936a6738363a2d8974ad2007b952/chrome/skin/status_add.png -------------------------------------------------------------------------------- /chrome/skin/status_closed.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tobiasstrebitzer/FireFile/0cc1cdd02884936a6738363a2d8974ad2007b952/chrome/skin/status_closed.png -------------------------------------------------------------------------------- /chrome/skin/status_disabled.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tobiasstrebitzer/FireFile/0cc1cdd02884936a6738363a2d8974ad2007b952/chrome/skin/status_disabled.png -------------------------------------------------------------------------------- /chrome/skin/status_open.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tobiasstrebitzer/FireFile/0cc1cdd02884936a6738363a2d8974ad2007b952/chrome/skin/status_open.png -------------------------------------------------------------------------------- /chrome/skin/widgets.css: -------------------------------------------------------------------------------- 1 | div#cssFireFilePanel input:-moz-placeholder { 2 | color: #999999; 3 | } 4 | 5 | /* Default state **************************************************************/ 6 | 7 | div#cssFireFilePanel :-moz-any(button, input[type='button'], input[type='submit'], select, input[type='checkbox'], input[type='radio']) { 8 | -moz-appearance: none; 9 | -moz-user-select: none; 10 | background-image: linear-gradient(#ededed, #ededed 38%, #dedede); 11 | border: 1px solid rgba(0, 0, 0, 0.25); 12 | border-radius: 2px; 13 | box-shadow: 0 1px 0 rgba(0, 0, 0, 0.08), inset 0 1px 2px rgba(255, 255, 255, 0.75); 14 | color: #444; 15 | font: inherit; 16 | margin: 0 1px 0 0; 17 | text-shadow: 0 1px 0 rgb(240, 240, 240); 18 | } 19 | 20 | div#cssFireFilePanel :-moz-any(button, input[type='button'], input[type='submit'], select) { 21 | min-height: 2em; 22 | min-width: 4em; 23 | } 24 | 25 | div#cssFireFilePanel :-moz-any(button, input[type='button'], input[type='submit']) { 26 | -moz-padding-end: 10px; 27 | -moz-padding-start: 10px; 28 | } 29 | 30 | div#cssFireFilePanel select { 31 | -moz-appearance: none; 32 | -moz-padding-end: 20px; 33 | -moz-padding-start: 6px; 34 | background-image: -moz-image-set(url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABMAAAAICAYAAAAbQcSUAAAAaUlEQVQoz2P4//8/A7UwdkEGhiggTsODo4g2LBEImJmZvwE1/UfHIHGQPNGGAbHCggULFrKxsf1ENgjEB4mD5EnxJoaByAZB5Yk3DNlAPj6+L8gGkWUYzMC3b982IRtEtmFQjaxYxDAwAGi4TwMYKNLfAAAAAElFTkSuQmCC') 1x, url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACcAAAAQCAYAAACV3GYgAAAAWklEQVRIx+3VOwoAIAwD0B49N686CCJ+K0aHFrIl8LaKqsqvEccxcPEQo8bgNs4KTBth4HaByCMWbhWIcsDEzYCoy2xcD4hW8QWuBqJXeoXLQIwK/iEc57iDBIg+ClNpjek/AAAAAElFTkSuQmCC') 2x), linear-gradient(#ededed, #ededed 38%, #dedede); 35 | background-position: right center; 36 | background-repeat: no-repeat; 37 | } 38 | 39 | div#cssFireFilePanel input[type='checkbox'] { 40 | bottom: 2px; 41 | height: 13px; 42 | position: relative; 43 | vertical-align: middle; 44 | width: 13px; 45 | } 46 | 47 | div#cssFireFilePanel input[type='radio'] { 48 | border-radius: 100%; 49 | bottom: 3px; 50 | height: 15px; 51 | position: relative; 52 | vertical-align: middle; 53 | width: 15px; 54 | } 55 | 56 | div#cssFireFilePanel :-moz-any(input[type='password'], input[type='search'], input[type='text'], input[type='url'], textarea) { 57 | border: 1px solid #bfbfbf; 58 | border-radius: 2px; 59 | box-sizing: border-box; 60 | color: #444; 61 | font: inherit; 62 | margin: 0; 63 | min-height: 2em; 64 | padding: 0px 3px; 65 | } 66 | 67 | /* Checked ********************************************************************/ 68 | 69 | div#cssFireFilePanel input[type='checkbox']:checked::before { 70 | -moz-user-select: none; 71 | background-image: -moz-image-set(url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAsAAAALCAYAAACprHcmAAAAcklEQVQY02NgwA/YoJgoEA/Es4DYgJBCJSBeD8SboRinBiYg7kZS2IosyQ/Eakh8LySFq4FYHFlxGRBvBOJYqMRqJMU+yApNkSRAeC0Sux3dfSCTetE0wKyXxOWhMKhTYIr9CAUXyJMzgLgBagBBgDPGAI2LGdNt0T1AAAAAAElFTkSuQmCC') 1x, url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABYAAAAWCAYAAADEtGw7AAAA60lEQVQ4y2P4//8/Ay0wA00NpgC4AXEksgA1DNYA4vVAvBnZcEoNFgLihVBDNyMbTonBLEDchWYo3HBKDM7BYSgIZ5JrsBseQxuBmIkcg5EjCx1PBmJufGHsBMQFQMxORGTB8BIglsCXKmSBeA1U8RQgliMistYBsTq+dAxy4TQ0TSBLnPFE1iYgdkAPL3SDC/BECi4cjS0i0A12RgoGYnAxEDMSYzAIyGMJDmy4B4jZcCUdXKmCnUCwzAVifnxpklA6xhY0K4BYgVBiJyaDgIJmKtTQjUBsTEwuIjbnwYLGi9jsSZ8aZEgZDACI3DQYaeTU0AAAAABJRU5ErkJggg==') 2x); 72 | background-size: 100% 100%; 73 | content: ''; 74 | display: block; 75 | height: 100%; 76 | width: 100%; 77 | } 78 | 79 | div#cssFireFilePanel input[type='radio']:checked::before { 80 | background-color: #666; 81 | border-radius: 100%; 82 | bottom: 3px; 83 | content: ''; 84 | display: block; 85 | left: 3px; 86 | position: absolute; 87 | right: 3px; 88 | top: 3px; 89 | } 90 | 91 | /* Hover **********************************************************************/ 92 | 93 | div#cssFireFilePanel :enabled:hover:-moz-any(select,input[type='checkbox'],input[type='radio'], button, input[type='button'], input[type='submit']) { 94 | background-image: linear-gradient(#f0f0f0, #f0f0f0 38%, #e0e0e0); 95 | border-color: rgba(0, 0, 0, 0.3); 96 | box-shadow: 0 1px 0 rgba(0, 0, 0, 0.12), inset 0 1px 2px rgba(255, 255, 255, 0.95); 97 | color: black; 98 | } 99 | 100 | div#cssFireFilePanel :enabled:hover:select { 101 | background-image: -moz-image-set(url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABMAAAAICAYAAAAbQcSUAAAAaUlEQVQoz2P4//8/A7UwdkEGhiggTsODo4g2LBEImJmZvwE1/UfHIHGQPNGGAbHCggULFrKxsf1ENgjEB4mD5EnxJoaByAZB5Yk3DNlAPj6+L8gGkWUYzMC3b982IRtEtmFQjaxYxDAwAGi4TwMYKNLfAAAAAElFTkSuQmCC') 1x, url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACcAAAAQCAYAAACV3GYgAAAAWklEQVRIx+3VOwoAIAwD0B49N686CCJ+K0aHFrIl8LaKqsqvEccxcPEQo8bgNs4KTBth4HaByCMWbhWIcsDEzYCoy2xcD4hW8QWuBqJXeoXLQIwK/iEc57iDBIg+ClNpjek/AAAAAElFTkSuQmCC') 2x), linear-gradient(#f0f0f0, #f0f0f0 38%, #e0e0e0); 102 | } 103 | 104 | /* Active *********************************************************************/ 105 | 106 | div#cssFireFilePanel :enabled:active:-moz-any(select, input[type='checkbox'], input[type='radio'], button, input[type='button'], input[type='submit']) { 107 | background-image: linear-gradient(#e7e7e7, #e7e7e7 38%, #d7d7d7); 108 | box-shadow: none; 109 | text-shadow: none; 110 | } 111 | 112 | div#cssFireFilePanel :enabled:active:select { 113 | background-image: -moz-image-set(url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABMAAAAICAYAAAAbQcSUAAAAaUlEQVQoz2P4//8/A7UwdkEGhiggTsODo4g2LBEImJmZvwE1/UfHIHGQPNGGAbHCggULFrKxsf1ENgjEB4mD5EnxJoaByAZB5Yk3DNlAPj6+L8gGkWUYzMC3b982IRtEtmFQjaxYxDAwAGi4TwMYKNLfAAAAAElFTkSuQmCC') 1x, url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACcAAAAQCAYAAACV3GYgAAAAWklEQVRIx+3VOwoAIAwD0B49N686CCJ+K0aHFrIl8LaKqsqvEccxcPEQo8bgNs4KTBth4HaByCMWbhWIcsDEzYCoy2xcD4hW8QWuBqJXeoXLQIwK/iEc57iDBIg+ClNpjek/AAAAAElFTkSuQmCC') 2x), linear-gradient(#e7e7e7, #e7e7e7 38%, #d7d7d7); 114 | } 115 | 116 | /* Disabled *******************************************************************/ 117 | 118 | div#cssFireFilePanel :disabled:-moz-any(button, input[type='button'], input[type='submit'], select) { 119 | background-image: linear-gradient(#f1f1f1, #f1f1f1 38%, #e6e6e6); 120 | border-color: rgba(80, 80, 80, 0.2); 121 | box-shadow: 0 1px 0 rgba(80, 80, 80, 0.08), inset 0 1px 2px rgba(255, 255, 255, 0.75); 122 | color: #aaa; 123 | } 124 | 125 | div#cssFireFilePanel select:disabled { 126 | background-image: -moz-image-set(url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABMAAAAICAYAAAAbQcSUAAAAWklEQVQoz2P4//8/A7UwdkEGhiggTsODo4g2LBEIGhoa/uPCIHmiDQNihQULFizEZhBIHCRPijexGggzCCpPvGHoBiIbRJZhMAPfvn3bhGwQ2YZBNbJiEcPAAIgGZrTRc1ZLAAAAAElFTkSuQmCC') 1x, url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACYAAAAQCAYAAAB6Hg0eAAAAX0lEQVRIx+3UOwoAIAxEwRz93TwWIoj4lwRBA9vtwlQRVZUbcyVqCUY8PQwWsFMcgFjBdnGkvSVsFUe+tYbN4ih3HrARjtrGC9bC0ep7wkocva43LOEY9d75/B/2YZsJM1B42fe2uWoAAAAASUVORK5CYII=') 2x), linear-gradient(#f1f1f1, #f1f1f1 38%, #e6e6e6); 127 | } 128 | 129 | div#cssFireFilePanel input:disabled:-moz-any([type='checkbox'], [type='radio']) { 130 | opacity: .75; 131 | } 132 | 133 | div#cssFireFilePanel input:disabled:-moz-any([type='password'], [type='search'], [type='text'], [type='url']) { 134 | color: #999; 135 | } 136 | 137 | /* Focus **********************************************************************/ 138 | 139 | div#cssFireFilePanel :enabled:focus:-moz-any(select, input[type='checkbox'], input[type='password'], input[type='radio'], input[type='search'], input[type='text'], input[type='url'], button, input[type='button'], input[type='submit']) { 140 | transition: border-color 200ms; 141 | border-color: rgb(77, 144, 254); 142 | outline: none; 143 | } 144 | 145 | div#cssFireFilePanel :-moz-any(.checkbox, .radio) label { 146 | display: -moz-inline-box; 147 | padding-bottom: 7px; 148 | padding-top: 7px; 149 | } 150 | 151 | div#cssFireFilePanel :-moz-any(.checkbox, .radio) label input ~ span { 152 | -moz-margin-start: 0.6em; 153 | display: block; 154 | } 155 | 156 | div#cssFireFilePanel :-moz-any(.checkbox, .radio) label:hover { 157 | color: black; 158 | } 159 | 160 | div#cssFireFilePanel label > input:disabled:-moz-any([type='checkbox'], [type='radio']) ~ span { 161 | color: #999; 162 | } -------------------------------------------------------------------------------- /defaults/preferences/default.js: -------------------------------------------------------------------------------- 1 | pref("extensions.firefile.sites", ""); 2 | pref("extensions.firefile.enable_notifications", true); 3 | pref("extensions.firefile.inspector_switch_css", true); 4 | pref("extensions.firefile.debug", false); 5 | pref("extensions.firefile.username", ""); 6 | pref("extensions.firefile.token", ""); -------------------------------------------------------------------------------- /icons/default/firefile.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tobiasstrebitzer/FireFile/0cc1cdd02884936a6738363a2d8974ad2007b952/icons/default/firefile.ico -------------------------------------------------------------------------------- /install.rdf: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | firefile@strebitzer.at 5 | 0.9.2 6 | 2 7 | true 8 | 9 | 10 | 11 | {ec8030f7-c20a-464f-9b0e-13a3a9e97384} 12 | 16.* 13 | 19.* 14 | 15 | 16 | 17 | chrome://FireFile/skin/firefile_32.png 18 | 19 | FireFile 20 | Firebug extension to save the CSS files edited with firebug live to your web server. 21 | Tobias Strebitzer 22 | http://www.firefile.at 23 | 24 | 25 | 26 | --------------------------------------------------------------------------------