--- a/cssParser.js Fri Mar 26 02:46:59 2010 -0500
+++ b/cssParser.js Sat Mar 27 11:36:12 2010 -0500
@@ -432,6 +432,8 @@
this.mPreserveWS = true;
this.mPreserveComments = true;
+
+ this.mPreservedTokens = [];
}
CSSParser.prototype = {
@@ -813,7 +815,7 @@
|| (token.isSymbol(")") && ontop == "(")
|| (token.isSymbol("]") && ontop == "[")) {
blocks.pop();
- if (!blocks.length)
+ if (!blocks.length && token.isSymbol("}"))
break;
}
}
@@ -873,7 +875,7 @@
parseImportRule: function(aToken, aSheet) {
var s = aToken.value;
- this.mScanner.preserveState();
+ this.preserveState();
var token = this.getToken(true, true);
var media = [];
var href = "";
@@ -909,7 +911,7 @@
if (token.isSymbol(";") && href && media.length) {
s += ";"
- this.mScanner.forgetState();
+ this.forgetState();
var rule = new jscsspImportRule();
rule.parsedCssText = s;
rule.href = href;
@@ -919,7 +921,7 @@
return true;
}
}
- this.mScanner.restoreState();
+ this.restoreState();
this.addUnknownAtRule(aSheet, "@import");
return false;
},
@@ -928,7 +930,7 @@
var s = token.value;
var declarations = [];
var valid = false;
- this.mScanner.preserveState();
+ this.preserveState();
token = this.getToken(true, true);
var media = [];
var foundMedia = false;
@@ -945,14 +947,14 @@
this.ungetToken();
else {
// error...
- token = null;
+ token.type = jscsspToken.NULL_TYPE;
break;
}
}
} else if (token.isSymbol("{"))
break;
else if (foundMedia) {
- token = null;
+ token.type = jscsspToken.NULL_TYPE;
// not a media list
break;
}
@@ -979,7 +981,7 @@
}
}
if (valid) {
- this.mScanner.forgetState();
+ this.forgetState();
var rule = new jscsspVariablesRule();
rule.parsedCssText = s;
rule.declarations = declarations;
@@ -988,14 +990,14 @@
aSheet.cssRules.push(rule)
return true;
}
- this.mScanner.restoreState();
+ this.restoreState();
return false;
},
parseNamespaceRule: function(aToken, aSheet) {
var s = aToken.value;
var valid = false;
- this.mScanner.preserveState();
+ this.preserveState();
var token = this.getToken(true, true);
if (token.isNotNull()) {
var prefix = "";
@@ -1016,9 +1018,9 @@
token = this.getToken(true, true);
var urlContent = this.parseURL(token);
if (urlContent) {
- url += urlContent;
+ url += "url(" + urlContent;
foundURL = true;
- s += " " + url;
+ s += " " + urlContent;
}
}
}
@@ -1026,7 +1028,7 @@
token = this.getToken(true, true);
if (token.isSymbol(";")) {
s += ";";
- this.mScanner.forgetState();
+ this.forgetState();
var rule = new jscsspNamespaceRule();
rule.parsedCssText = s;
rule.prefix = prefix;
@@ -1038,7 +1040,7 @@
}
}
- this.mScanner.restoreState();
+ this.restoreState();
this.addUnknownAtRule(aSheet, "@namespace");
return false;
},
@@ -1047,7 +1049,7 @@
var s = aToken.value;
var valid = false;
var descriptors = [];
- this.mScanner.preserveState();
+ this.preserveState();
var token = this.getToken(true, true);
if (token.isNotNull()) {
// expecting block start
@@ -1068,7 +1070,7 @@
}
}
if (valid) {
- this.mScanner.forgetState();
+ this.forgetState();
var rule = new jscsspFontFaceRule();
rule.parsedCssText = s;
rule.descriptors = descriptors;
@@ -1076,7 +1078,7 @@
aSheet.cssRules.push(rule)
return true;
}
- this.mScanner.restoreState();
+ this.restoreState();
return false;
},
@@ -1084,14 +1086,17 @@
var s = aToken.value;
var valid = false;
var declarations = [];
- this.mScanner.preserveState();
+ this.preserveState();
var token = this.getToken(true, true);
var pageSelector = "";
- if (token.isSymbol(":")) {
- token = this.getToken(false, false);
+ if (token.isSymbol(":") || token.isIdent()) {
+ if (token.isSymbol(":")) {
+ pageSelector = ":";
+ token = this.getToken(false, false);
+ }
if (token.isIdent()) {
- pageSelector = token.value;
- s += " :" + token.value;
+ pageSelector += token.value;
+ s += " " + pageSelector;
token = this.getToken(true, true);
}
}
@@ -1114,7 +1119,7 @@
}
}
if (valid) {
- this.mScanner.forgetState();
+ this.forgetState();
var rule = new jscsspPageRule();
rule.parsedCssText = s;
rule.pageSelector = pageSelector;
@@ -1123,7 +1128,7 @@
aSheet.cssRules.push(rule)
return true;
}
- this.mScanner.restoreState();
+ this.restoreState();
return false;
},
@@ -1228,7 +1233,7 @@
token = this.getToken(false, true);
}
if (values.length && valueText) {
- this.mScanner.forgetState();
+ this.forgetState();
aDecl.push(this._createJscsspDeclarationFromValuesArray(descriptor, values, valueText));
return valueText;
}
@@ -1303,7 +1308,7 @@
default:
return "";
}
- this.mScanner.forgetState();
+ this.forgetState();
aDecl.push(this._createJscsspDeclarationFromValue(aProperty + "-top", top));
aDecl.push(this._createJscsspDeclarationFromValue(aProperty + "-right", right));
aDecl.push(this._createJscsspDeclarationFromValue(aProperty + "-bottom", bottom));
@@ -1378,7 +1383,7 @@
default:
return "";
}
- this.mScanner.forgetState();
+ this.forgetState();
aDecl.push(this._createJscsspDeclarationFromValue("border-top-color", top));
aDecl.push(this._createJscsspDeclarationFromValue("border-right-color", right));
aDecl.push(this._createJscsspDeclarationFromValue("border-bottom-color", bottom));
@@ -1440,7 +1445,7 @@
default:
return "";
}
- this.mScanner.forgetState();
+ this.forgetState();
aDecl.push(this._createJscsspDeclarationFromValue("cue-before", before));
aDecl.push(this._createJscsspDeclarationFromValue("cue-after", after));
return before + " " + after;
@@ -1494,7 +1499,7 @@
default:
return "";
}
- this.mScanner.forgetState();
+ this.forgetState();
aDecl.push(this._createJscsspDeclarationFromValue("pause-before", before));
aDecl.push(this._createJscsspDeclarationFromValue("pause-after", after));
return before + " " + after;
@@ -1565,7 +1570,7 @@
default:
return "";
}
- this.mScanner.forgetState();
+ this.forgetState();
aDecl.push(this._createJscsspDeclarationFromValue("border-top-width", top));
aDecl.push(this._createJscsspDeclarationFromValue("border-right-width", right));
aDecl.push(this._createJscsspDeclarationFromValue("border-bottom-width", bottom));
@@ -1636,7 +1641,7 @@
default:
return "";
}
- this.mScanner.forgetState();
+ this.forgetState();
aDecl.push(this._createJscsspDeclarationFromValue("border-top-style", top));
aDecl.push(this._createJscsspDeclarationFromValue("border-right-style", right));
aDecl.push(this._createJscsspDeclarationFromValue("border-bottom-style", bottom));
@@ -1693,7 +1698,7 @@
}
// create the declarations
- this.mScanner.forgetState();
+ this.forgetState();
bWidth = bWidth ? bWidth : "medium";
bStyle = bStyle ? bStyle : "none";
bColor = bColor ? bColor : "-moz-initial";
@@ -1814,7 +1819,7 @@
}
// create the declarations
- this.mScanner.forgetState();
+ this.forgetState();
bgColor = bgColor ? bgColor : "transparent";
bgImage = bgImage ? bgImage : "none";
bgRepeat = bgRepeat ? bgRepeat : "repeat";
@@ -1883,7 +1888,7 @@
}
// create the declarations
- this.mScanner.forgetState();
+ this.forgetState();
lType = lType ? lType : "none";
lImage = lImage ? lImage : "none";
lPosition = lPosition ? lPosition : "outside";
@@ -2042,7 +2047,7 @@
}
// create the declarations
- this.mScanner.forgetState();
+ this.forgetState();
if (fSystem) {
aDecl.push(this._createJscsspDeclarationFromValue("font", fSystem));
return fSystem;
@@ -2264,7 +2269,7 @@
},
parseDeclaration: function(aToken, aDecl, aAcceptPriority, aExpandShorthands, aSheet) {
- this.mScanner.preserveState();
+ this.preserveState();
var blocks = [];
if (aToken.isIdent()) {
var descriptor = aToken.value.toLowerCase();
@@ -2347,7 +2352,7 @@
}
else if (aToken.isComment()) {
if (this.mPreserveComments) {
- this.mScanner.forgetState();
+ this.forgetState();
var comment = new jscsspComment();
comment.parsedCssText = aToken.value;
aDecl.push(comment);
@@ -2356,7 +2361,7 @@
}
// we have an error here, let's skip it
- this.mScanner.restoreState();
+ this.restoreState();
var s = aToken.value;
blocks = [];
var token = this.getToken(false, false);
@@ -2392,7 +2397,7 @@
var s = aToken.value;
var valid = false;
var mediaRule = new jscsspMediaRule();
- this.mScanner.preserveState();
+ this.preserveState();
var token = this.getToken(true, true);
var foundMedia = false;
while (token.isNotNull()) {
@@ -2408,20 +2413,20 @@
this.ungetToken();
else {
// error...
- token = null;
+ token.type = jscsspToken.NULL_TYPE;
break;
}
}
} else if (token.isSymbol("{"))
break;
else if (foundMedia) {
- token = null;
+ token.type = jscsspToken.NULL_TYPE;
// not a media list
break;
}
token = this.getToken(true, true);
}
- if (token.isSymbol("{")) {
+ if (token.isSymbol("{") && mediaRule.media.length) {
// ok let's parse style rules now...
s += " { ";
token = this.getToken(true, false);
@@ -2443,12 +2448,12 @@
}
}
if (valid) {
- this.mScanner.forgetState();
+ this.forgetState();
mediaRule.parsedCssText = s;
aSheet.cssRules.push(mediaRule);
return true;
}
- this.mScanner.restoreState();
+ this.restoreState();
return false;
},
@@ -2465,6 +2470,7 @@
parseStyleRule: function(aToken, aOwner, aIsInsideMediaRule)
{
+ this.preserveState();
// first let's see if we have a selector here...
var selector = this.parseSelector(aToken, false);
var valid = false;
@@ -2493,6 +2499,10 @@
}
}
}
+ else {
+ // selector is invalid so the whole rule is invalid with it
+ }
+
if (valid) {
var rule = new jscsspStyleRule();
rule.parsedCssText = s;
@@ -2505,6 +2515,9 @@
aOwner.cssRules.push(rule);
return s;
}
+ this.restoreState();
+ s = this.currentToken().value;
+ this.addUnknownAtRule(aOwner, s);
return "";
},
@@ -2679,6 +2692,8 @@
else
return null;
}
+ else
+ return null;
// nothing, =, *=, $=, ^=, |=
token = this.getToken(true, true);
@@ -2689,30 +2704,54 @@
|| token.isContainsmatch()
|| token.isSymbol("=")) {
s += token.value;
- } else
- return null;
-
- token = this.getToken(true, true);
- if (token.isString() || token.isIdent())
+ token = this.getToken(true, true);
+ if (token.isString() || token.isIdent()) {
+ s += token.value;
+ token = this.getToken(true, true);
+ }
+ else
+ return null;
+
+ if (token.isSymbol("]"))
+ s += token.value;
+ else
+ return null;
+ }
+ else if (token.isSymbol("]"))
s += token.value;
else
return null;
-
- token = this.getToken(true, true);
- if (token.isSymbol("]"))
- s += token.value;
- else
- return null;
+
}
return s;
},
+ preserveState: function() {
+ this.mPreservedTokens.push(this.currentToken());
+ this.mScanner.preserveState();
+ },
+
+ restoreState: function() {
+ if (this.mPreservedTokens.length) {
+ this.mScanner.restoreState();
+ this.mToken = this.mPreservedTokens.pop();
+ }
+ },
+
+ forgetState: function() {
+ if (this.mPreservedTokens.length) {
+ this.mScanner.forgetState();
+ this.mPreservedTokens.pop();
+ }
+ },
+
parse: function(aString, aTryToPreserveWhitespaces, aTryToPreserveComments) {
if (!aString)
return null; // early way out if we can
this.mPreserveWS = aTryToPreserveWhitespaces;
this.mPreserveComments = aTryToPreserveComments;
+ this.mPreservedTokens = [];
this.mScanner.init(aString);
var sheet = new jscsspStylesheet();
@@ -2722,6 +2761,7 @@
return;
if (token.isAtRule("@charset")) {
this.parseCharsetRule(token, sheet);
+ token = this.getToken(false, false);
}
var foundStyleRules = false;
@@ -2790,8 +2830,9 @@
else // plain style rules
{
- this.parseStyleRule(token, sheet, false);
- foundStyleRules = true;
+ var ruleText = this.parseStyleRule(token, sheet, false);
+ if (ruleText)
+ foundStyleRules = true;
}
token = this.getToken(false);
}
@@ -2980,6 +3021,13 @@
return rv;
},
+ htmlText: function() {
+ var rv = "";
+ for (var i = 0; i < this.cssRules.length; i++)
+ rv += this.cssRules[i].htmlText() + "<br>";
+ return rv;
+ },
+
resolveVariables: function(aMedium) {
function ItemFoundInArray(aArray, aItem) {
@@ -3025,6 +3073,11 @@
return "@charset " + this.encoding + ";";
},
+ htmlText: function() {
+ return "<span class='atrule'>@charset</span> <span class='string'>"
+ + this.encoding + "</span>;";
+ },
+
setCssText: function(val) {
var sheet = {cssRules: []};
var parser = new CSSParser(val);
@@ -3054,6 +3107,10 @@
jscsspErrorRule.prototype = {
cssText: function() {
return this.parsedCssText;
+ },
+
+ htmlText: function() {
+ return "<span class='error'>" + this.parsedCssText + "</span>";
}
};
@@ -3072,6 +3129,10 @@
return this.parsedCssText;
},
+ htmlText: function() {
+ return "<span class='comment'>" + this.parsedCssText + "</span>";
+ },
+
setCssText: function(val) {
var parser = new CSSParser(val);
var token = parser.getToken(true, false);
@@ -3092,6 +3153,17 @@
this.parentRule = null;
}
+jscsspWhitespace.prototype = {
+ cssText: function() {
+ return this.parsedCssText;
+ },
+
+ htmlText: function() {
+ return this.cssText().replace( / /g , " ")
+ .replace( /\n/g , "<br>");
+ },
+};
+
/* kJscsspIMPORT_RULE */
function jscsspImportRule()
@@ -3112,6 +3184,16 @@
+ ";";
},
+ htmlText: function() {
+ var mediaString = "";
+ if (this.media.length)
+ mediaString = "<span class='medium'>" + this.media.join("</span>, <span class='medium'>")
+ + "</span>";
+ return "<span class='atrule'>@import</span> " + (mediaString ? mediaString + " " : "")
+ + "<span class='url'>" + this.href + "</span>"
+ + ";";
+ },
+
setCssText: function(val) {
var sheet = {cssRules: []};
var parser = new CSSParser(val);
@@ -3143,11 +3225,17 @@
jscsspNamespaceRule.prototype = {
cssText: function() {
- return "@namespace" + (this.prefix ? this.prefix + " ": "")
+ return "@namespace " + (this.prefix ? this.prefix + " ": "")
+ this.url
+ ";";
},
+ htmlText: function() {
+ return "<span class='atrule'>@namespace</span> " + (this.prefix ? this.prefix + " ": "")
+ + "<span class='url'>" + this.url + "</span>"
+ + ";";
+ },
+
setCssText: function(val) {
var sheet = {cssRules: []};
var parser = new CSSParser(val);
@@ -3186,6 +3274,17 @@
"voice-family": true
},
+ htmlText: function() {
+ var rv = "<span class='property'>" + this.property + "</span>: ";
+ var separator = (this.property in this.kCOMMA_SEPARATED) ? ", " : " ";
+ for (var i = 0; i < this.values.length; i++)
+ if (this.values[i].cssText() != null)
+ rv += (i ? separator : "") + "<span class='value'>" + this.values[i].cssText() + "</span>";
+ else
+ return null;
+ return rv + (this.priority ? " <span class='bang'>!important</span>" : "") + ";";
+ },
+
cssText: function() {
var rv = this.property + ": ";
var separator = (this.property in this.kCOMMA_SEPARATED) ? ", " : " ";
@@ -3237,6 +3336,16 @@
return rv + gTABS + "}";
},
+ htmlText: function() {
+ var rv = gTABS + "<span class='atrule'>@font-face</span> {<br>";
+ var preservedGTABS = gTABS;
+ gTABS += " ";
+ for (var i = 0; i < this.descriptors.length; i++)
+ rv += gTABS + this.descriptors[i].htmlText() + "<br>";
+ gTABS = preservedGTABS;
+ return rv + gTABS + "}";
+ },
+
setCssText: function(val) {
var sheet = {cssRules: []};
var parser = new CSSParser(val);
@@ -3276,6 +3385,20 @@
return rv + gTABS + "}";
},
+ htmlText: function() {
+ var mediaString = "";
+ if (this.media.length)
+ mediaString = "<span class='medium'>" + this.media.join("</span>, <span class='medium'>")
+ + "</span>";
+ var rv = gTABS + "<span class='atrule'>@media</span> " + mediaString + " {<br>";
+ var preservedGTABS = gTABS;
+ gTABS += " ";
+ for (var i = 0; i < this.cssRules.length; i++)
+ rv += gTABS + this.cssRules[i].htmlText() + "<br>";
+ gTABS = preservedGTABS;
+ return rv + gTABS + "}";
+ },
+
setCssText: function(val) {
var sheet = {cssRules: []};
var parser = new CSSParser(val);
@@ -3319,6 +3442,19 @@
return rv + gTABS + "}";
},
+ htmlText: function() {
+ var rv = "<span class='selector'>" + this.mSelectorText + "</span> {<br>";
+ var preservedGTABS = gTABS;
+ gTABS += " ";
+ for (var i = 0; i < this.declarations.length; i++) {
+ var declText = this.declarations[i].htmlText();
+ if (declText)
+ rv += gTABS + this.declarations[i].htmlText() + "<br>";
+ }
+ gTABS = preservedGTABS;
+ return rv + gTABS + "}";
+ },
+
setCssText: function(val) {
var sheet = {cssRules: []};
var parser = new CSSParser(val);
@@ -3367,8 +3503,9 @@
jscsspPageRule.prototype = {
cssText: function() {
- var rv = gTABS + "@page " + (this.mediaSelector ? this.mediaSelector : "")
- + " {\n";
+ var rv = gTABS + "@page "
+ + (this.pageSelector ? this.pageSelector + " ": "")
+ + "{\n";
var preservedGTABS = gTABS;
gTABS += " ";
for (var i = 0; i < this.declarations.length; i++)
@@ -3377,6 +3514,18 @@
return rv + gTABS + "}";
},
+ htmlText: function() {
+ var rv = gTABS + "<span class='atrule'>@page</span> "
+ + (this.pageSelector ? "<span class='selector'>" + this.pageSelector + "</span> " : "")
+ + "{<br>";
+ var preservedGTABS = gTABS;
+ gTABS += " ";
+ for (var i = 0; i < this.declarations.length; i++)
+ rv += gTABS + this.declarations[i].htmlText() + "<br>";
+ gTABS = preservedGTABS;
+ return rv + gTABS + "}";
+ },
+
setCssText: function(val) {
var sheet = {cssRules: []};
var parser = new CSSParser(val);
@@ -3419,6 +3568,22 @@
return rv + gTABS + "}";
},
+ htmlText: function() {
+ var mediaString = "";
+ if (this.media.length)
+ mediaString = "<span class='medium'>" + this.media.join("</span>, <span class='medium'>")
+ + "</span>";
+ var rv = gTABS + "<span class='atrule'>@variables</span> " +
+ (mediaString ? mediaString + " " : "") +
+ "{<br>";
+ var preservedGTABS = gTABS;
+ gTABS += " ";
+ for (var i = 0; i < this.declarations.length; i++)
+ rv += gTABS + this.declarations[i].htmlText() + "<br>";
+ gTABS = preservedGTABS;
+ return rv + gTABS + "}";
+ },
+
setCssText: function(val) {
var sheet = {cssRules: []};
var parser = new CSSParser(val);