| /* ***** BEGIN LICENSE BLOCK ***** |
| * Version: MPL 1.1 |
| * |
| * The contents of this file are subject to the Mozilla Public License Version |
| * 1.1 (the "License"); you may not use this file except in compliance with |
| * the License. You may obtain a copy of the License at |
| * http://www.mozilla.org/MPL/ |
| * |
| * Software distributed under the License is distributed on an "AS IS" basis, |
| * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License |
| * for the specific language governing rights and limitations under the |
| * License. |
| * |
| * The Original Code is jquery-css-parser. |
| * |
| * The Initial Developer of the Original Code is Daniel Wachsstock. |
| * Portions created by the Initial Developer are Copyright (C) 2009 |
| * the Initial Developer. All Rights Reserved. |
| * |
| * Contributor(s): |
| * Bespin Team (bespin@mozilla.com) |
| * |
| * ORIGINAL MIT-licensed CODE LICENSE HEADER FOLLOWS: |
| |
| // jQuery based CSS parser |
| // documentation: http://youngisrael-stl.org/wordpress/2009/01/16/jquery-css-parser/ |
| // Version: 1.0 |
| // Copyright (c) 2009 Daniel Wachsstock |
| // MIT license: |
| // Permission is hereby granted, free of charge, to any person |
| // obtaining a copy of this software and associated documentation |
| // files (the "Software"), to deal in the Software without |
| // restriction, including without limitation the rights to use, |
| // copy, modify, merge, publish, distribute, sublicense, and/or sell |
| // copies of the Software, and to permit persons to whom the |
| // Software is furnished to do so, subject to the following |
| // conditions: |
| |
| // The above copyright notice and this permission notice shall be |
| // included in all copies or substantial portions of the Software. |
| |
| // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, |
| // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES |
| // OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND |
| // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT |
| // HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, |
| // WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING |
| // FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR |
| // OTHER DEALINGS IN THE SOFTWARE. |
| * ***** END LICENSE BLOCK ***** */ |
| |
| |
| dojo.provide("th.css"); |
| |
| dojo.declare("th.css.CSSParser", null, { |
| parse: function(str, ret) { |
| // parses the passed stylesheet into an object with properties containing objects with the attribute names and values |
| if (!ret) ret = {}; |
| |
| dojo.forEach(this.munge(str, false).split('`b%'), function(css){ |
| css = css.split('%b`'); // css[0] is the selector; css[1] is the index in munged for the cssText |
| if (css.length < 2) return; // invalid css |
| css[0] = this.restore(css[0]); |
| var obj = ret[css[0]] || {}; |
| ret[css[0]] = dojo.mixin(obj, this.parsedeclarations(css[1])); |
| }, this); |
| |
| return ret; |
| }, |
| |
| // replace strings and brace-surrounded blocks with %s`number`s% and %b`number`b%. By successively taking out the innermost |
| // blocks, we ensure that we're matching braces. No way to do this with just regular expressions. Obviously, this assumes no one |
| // would use %s` in the real world. |
| // Turns out this is similar to the method that Dean Edwards used for his CSS parser in IE7.js (http://code.google.com/p/ie7-js/) |
| REbraces: /{[^{}]*}/, |
| |
| REfull: /\[[^\[\]]*\]|{[^{}]*}|\([^()]*\)|function(\s+\w+)?(\s*%b`\d+`b%){2}/, // match pairs of parentheses, brackets, and braces and function definitions. |
| |
| REatcomment: /\/\*@((?:[^\*]|\*[^\/])*)\*\//g, // comments of the form /*@ text */ have text parsed |
| // we have to combine the comments and the strings because comments can contain string delimiters and strings can contain comment delimiters |
| // var REcomment = /\/\*(?:[^\*]|\*[^\/])*\*\/|<!--|-->/g; // other comments are stripped. (this is a simplification of real SGML comments (see http://htmlhelp.com/reference/wilbur/misc/comment.html) , but it's what real browsers use) |
| // var REstring = /\\.|"(?:[^\\\"]|\\.|\\\n)*"|'(?:[^\\\']|\\.|\\\n)*'/g; // match escaped characters and strings |
| |
| REcomment_string: |
| /(?:\/\*(?:[^\*]|\*[^\/])*\*\/)|(\\.|"(?:[^\\\"]|\\.|\\\n)*"|'(?:[^\\\']|\\.|\\\n)*')/g, |
| |
| REmunged: /%\w`(\d+)`\w%/, |
| |
| uid: 0, // unique id number |
| |
| munged: {}, // strings that were removed by the parser so they don't mess up searching for specific characters |
| |
| munge: function(str, full) { |
| str = str |
| .replace(this.REatcomment, '$1') // strip /*@ comments but leave the text (to let invalid CSS through) |
| .replace(this.REcomment_string, dojo.hitch(this, function (s, string) { // strip strings and escaped characters, leaving munged markers, and strip comments |
| if (!string) return ''; |
| var replacement = '%s`'+(++this.uid)+'`s%'; |
| this.munged[this.uid] = string.replace(/^\\/, ''); // strip the backslash now |
| return replacement; |
| })); |
| |
| // need a loop here rather than .replace since we need to replace nested braces |
| var RE = full ? this.REfull : this.REbraces; |
| while (match = RE.exec(str)) { |
| replacement = '%b`'+(++this.uid)+'`b%'; |
| this.munged[this.uid] = match[0]; |
| str = str.replace(RE, replacement); |
| } |
| return str; |
| }, |
| |
| restore: function(str) { |
| if (str === undefined) return str; |
| while (match = this.REmunged.exec(str)) { |
| str = str.replace(this.REmunged, this.munged[match[1]]); |
| } |
| return dojo.trim(str); |
| }, |
| |
| parsedeclarations: function(index){ // take a string from the munged array and parse it into an object of property: value pairs |
| var str = this.munged[index].replace(/(?:^\s*[{'"]\s*)|(?:\s*([^\\])[}'"]\s*$)/g, '$1'); // find the string and remove the surrounding braces or quotes |
| str = this.munge(str); // make sure any internal braces or strings are escaped |
| var parsed = {}; |
| dojo.forEach(str.split(';'), function (decl) { |
| decl = decl.split(':'); |
| if (decl.length < 2) return; |
| parsed[this.restore(decl[0])] = this.restore(decl[1]); |
| }, this); |
| return parsed; |
| } |
| }); |