added capturing selector source text (to preserve namespace prefixes)

This commit is contained in:
peterl%netscape.com 1999-02-07 21:48:27 +00:00
parent 02a4a1f333
commit 7d519ac6c1
3 changed files with 78 additions and 9 deletions
content/html/style/src
layout

@ -63,6 +63,7 @@ struct SelectorList {
nsCSSSelector* mSelectors; nsCSSSelector* mSelectors;
SelectorList* mNext; SelectorList* mNext;
nsAutoString mSourceString;
}; };
SelectorList::SelectorList(void) SelectorList::SelectorList(void)
@ -148,7 +149,7 @@ protected:
PRBool ParseSelectorList(PRInt32& aErrorCode, SelectorList*& aListHead); PRBool ParseSelectorList(PRInt32& aErrorCode, SelectorList*& aListHead);
PRBool ParseSelectorGroup(PRInt32& aErrorCode, SelectorList*& aListHead); PRBool ParseSelectorGroup(PRInt32& aErrorCode, SelectorList*& aListHead);
PRBool ParseSelector(PRInt32& aErrorCode, nsCSSSelector& aSelectorResult); PRBool ParseSelector(PRInt32& aErrorCode, nsCSSSelector& aSelectorResult, nsString& aSource);
nsICSSDeclaration* ParseDeclarationBlock(PRInt32& aErrorCode, nsICSSDeclaration* ParseDeclarationBlock(PRInt32& aErrorCode,
PRBool aCheckForBraces); PRBool aCheckForBraces);
PRBool ParseDeclaration(PRInt32& aErrorCode, PRBool ParseDeclaration(PRInt32& aErrorCode,
@ -929,6 +930,7 @@ PRBool CSSParserImpl::ParseRuleSet(PRInt32& aErrorCode)
} }
rule->SetDeclaration(declaration); rule->SetDeclaration(declaration);
rule->SetWeight(weight); rule->SetWeight(weight);
rule->SetSourceSelectorText(list->mSourceString); // capture the original input (need this for namespace prefixes)
// rule->List(); // rule->List();
mSheet->AppendStyleRule(rule); mSheet->AppendStyleRule(rule);
NS_RELEASE(rule); NS_RELEASE(rule);
@ -1015,15 +1017,17 @@ static PRBool IsSinglePseudoClass(const nsCSSSelector& aSelector)
PRBool CSSParserImpl::ParseSelectorGroup(PRInt32& aErrorCode, PRBool CSSParserImpl::ParseSelectorGroup(PRInt32& aErrorCode,
SelectorList*& aList) SelectorList*& aList)
{ {
nsAutoString sourceBuffer;
SelectorList* list = nsnull; SelectorList* list = nsnull;
for (;;) { for (;;) {
nsCSSSelector selector; nsCSSSelector selector;
if (! ParseSelector(aErrorCode, selector)) { if (! ParseSelector(aErrorCode, selector, sourceBuffer)) {
break; break;
} }
if (nsnull == list) { if (nsnull == list) {
list = new SelectorList(); list = new SelectorList();
} }
sourceBuffer.Append(PRUnichar(' '));
list->AddSelector(selector); list->AddSelector(selector);
nsCSSSelector* listSel = list->mSelectors; nsCSSSelector* listSel = list->mSelectors;
// XXX parse combinator here // XXX parse combinator here
@ -1060,6 +1064,10 @@ PRBool CSSParserImpl::ParseSelectorGroup(PRInt32& aErrorCode,
} }
} }
aList = list; aList = list;
if (nsnull != list) {
sourceBuffer.Truncate(sourceBuffer.Length() - 1); // kill trailing space
list->mSourceString = sourceBuffer;
}
return PRBool(nsnull != aList); return PRBool(nsnull != aList);
} }
@ -1076,7 +1084,8 @@ PRBool CSSParserImpl::ParseSelectorGroup(PRInt32& aErrorCode,
* operator? [namespace \:]? element_name? [ ID | class | attrib | pseudo ]* * operator? [namespace \:]? element_name? [ ID | class | attrib | pseudo ]*
*/ */
PRBool CSSParserImpl::ParseSelector(PRInt32& aErrorCode, PRBool CSSParserImpl::ParseSelector(PRInt32& aErrorCode,
nsCSSSelector& aSelector) nsCSSSelector& aSelector,
nsString& aSource)
{ {
PRInt32 dataMask = 0; PRInt32 dataMask = 0;
nsAutoString buffer; nsAutoString buffer;
@ -1086,12 +1095,14 @@ PRBool CSSParserImpl::ParseSelector(PRInt32& aErrorCode,
} }
if ((eCSSToken_Symbol == mToken.mType) && ('*' == mToken.mSymbol)) { // universal element selector if ((eCSSToken_Symbol == mToken.mType) && ('*' == mToken.mSymbol)) { // universal element selector
// don't set any tag in the selector // don't set any tag in the selector
mToken.AppendToString(aSource);
dataMask |= SEL_MASK_ELEM; dataMask |= SEL_MASK_ELEM;
if (! GetToken(aErrorCode, PR_FALSE)) { // premature eof is ok (here!) if (! GetToken(aErrorCode, PR_FALSE)) { // premature eof is ok (here!)
return PR_TRUE; return PR_TRUE;
} }
} }
else if (eCSSToken_Ident == mToken.mType) { // element name else if (eCSSToken_Ident == mToken.mType) { // element name
mToken.AppendToString(aSource);
PRInt32 colon = mToken.mIdent.Find(':'); PRInt32 colon = mToken.mIdent.Find(':');
if (-1 == colon) { // no namespace if (-1 == colon) { // no namespace
if (mCaseSensitive) { if (mCaseSensitive) {
@ -1123,6 +1134,7 @@ PRBool CSSParserImpl::ParseSelector(PRInt32& aErrorCode,
if ((0 == (dataMask & SEL_MASK_ID)) && // only one ID if ((0 == (dataMask & SEL_MASK_ID)) && // only one ID
(0 < mToken.mIdent.Length()) && (0 < mToken.mIdent.Length()) &&
(nsString::IsAlpha(mToken.mIdent.CharAt(0)))) { // verify is legal ID (nsString::IsAlpha(mToken.mIdent.CharAt(0)))) { // verify is legal ID
mToken.AppendToString(aSource);
dataMask |= SEL_MASK_ID; dataMask |= SEL_MASK_ID;
aSelector.SetID(mToken.mIdent); aSelector.SetID(mToken.mIdent);
} }
@ -1132,6 +1144,7 @@ PRBool CSSParserImpl::ParseSelector(PRInt32& aErrorCode,
} }
} }
else if ((eCSSToken_Symbol == mToken.mType) && ('.' == mToken.mSymbol)) { // .class else if ((eCSSToken_Symbol == mToken.mType) && ('.' == mToken.mSymbol)) { // .class
mToken.AppendToString(aSource);
if (! GetToken(aErrorCode, PR_FALSE)) { // get ident if (! GetToken(aErrorCode, PR_FALSE)) { // get ident
return PR_FALSE; return PR_FALSE;
} }
@ -1139,6 +1152,7 @@ PRBool CSSParserImpl::ParseSelector(PRInt32& aErrorCode,
UngetToken(); UngetToken();
return PR_FALSE; return PR_FALSE;
} }
mToken.AppendToString(aSource);
dataMask |= SEL_MASK_CLASS; dataMask |= SEL_MASK_CLASS;
if (mCaseSensitive) { if (mCaseSensitive) {
aSelector.AddClass(mToken.mIdent); aSelector.AddClass(mToken.mIdent);
@ -1149,6 +1163,7 @@ PRBool CSSParserImpl::ParseSelector(PRInt32& aErrorCode,
} }
} }
else if ((eCSSToken_Symbol == mToken.mType) && (':' == mToken.mSymbol)) { // :pseudo else if ((eCSSToken_Symbol == mToken.mType) && (':' == mToken.mSymbol)) { // :pseudo
mToken.AppendToString(aSource);
if (! GetToken(aErrorCode, PR_FALSE)) { // premature eof if (! GetToken(aErrorCode, PR_FALSE)) { // premature eof
return PR_FALSE; return PR_FALSE;
} }
@ -1156,6 +1171,7 @@ PRBool CSSParserImpl::ParseSelector(PRInt32& aErrorCode,
UngetToken(); UngetToken();
return PR_FALSE; return PR_FALSE;
} }
mToken.AppendToString(aSource);
buffer.Truncate(); buffer.Truncate();
buffer.Append(':'); buffer.Append(':');
buffer.Append(mToken.mIdent); buffer.Append(mToken.mIdent);
@ -1192,6 +1208,7 @@ PRBool CSSParserImpl::ParseSelector(PRInt32& aErrorCode,
NS_RELEASE(pseudo); NS_RELEASE(pseudo);
} }
else if ((eCSSToken_Symbol == mToken.mType) && ('[' == mToken.mSymbol)) { // attribute else if ((eCSSToken_Symbol == mToken.mType) && ('[' == mToken.mSymbol)) { // attribute
mToken.AppendToString(aSource);
if (! GetToken(aErrorCode, PR_FALSE)) { // premature EOF if (! GetToken(aErrorCode, PR_FALSE)) { // premature EOF
return PR_FALSE; return PR_FALSE;
} }
@ -1199,6 +1216,7 @@ PRBool CSSParserImpl::ParseSelector(PRInt32& aErrorCode,
UngetToken(); UngetToken();
return PR_FALSE; return PR_FALSE;
} }
mToken.AppendToString(aSource);
nsAutoString attr(mToken.mIdent); nsAutoString attr(mToken.mIdent);
if (! mCaseSensitive) { if (! mCaseSensitive) {
attr.ToUpperCase(); attr.ToUpperCase();
@ -1207,6 +1225,7 @@ PRBool CSSParserImpl::ParseSelector(PRInt32& aErrorCode,
return PR_FALSE; return PR_FALSE;
} }
if (eCSSToken_Symbol == mToken.mType) { if (eCSSToken_Symbol == mToken.mType) {
mToken.AppendToString(aSource);
PRUint8 func; PRUint8 func;
if (']' == mToken.mSymbol) { if (']' == mToken.mSymbol) {
dataMask |= SEL_MASK_ATTRIB; dataMask |= SEL_MASK_ATTRIB;
@ -1220,6 +1239,7 @@ PRBool CSSParserImpl::ParseSelector(PRInt32& aErrorCode,
if (! GetToken(aErrorCode, PR_FALSE)) { // premature EOF if (! GetToken(aErrorCode, PR_FALSE)) { // premature EOF
return PR_FALSE; return PR_FALSE;
} }
mToken.AppendToString(aSource);
if ((eCSSToken_Symbol == mToken.mType) && ('=' == mToken.mSymbol)) { if ((eCSSToken_Symbol == mToken.mType) && ('=' == mToken.mSymbol)) {
func = NS_ATTR_FUNC_INCLUDES; func = NS_ATTR_FUNC_INCLUDES;
} }
@ -1232,6 +1252,7 @@ PRBool CSSParserImpl::ParseSelector(PRInt32& aErrorCode,
if (! GetToken(aErrorCode, PR_FALSE)) { // premature EOF if (! GetToken(aErrorCode, PR_FALSE)) { // premature EOF
return PR_FALSE; return PR_FALSE;
} }
mToken.AppendToString(aSource);
if ((eCSSToken_Symbol == mToken.mType) && ('=' == mToken.mSymbol)) { if ((eCSSToken_Symbol == mToken.mType) && ('=' == mToken.mSymbol)) {
func = NS_ATTR_FUNC_DASHMATCH; func = NS_ATTR_FUNC_DASHMATCH;
} }
@ -1249,11 +1270,13 @@ PRBool CSSParserImpl::ParseSelector(PRInt32& aErrorCode,
return PR_FALSE; return PR_FALSE;
} }
if ((eCSSToken_Ident == mToken.mType) || (eCSSToken_String == mToken.mType)) { if ((eCSSToken_Ident == mToken.mType) || (eCSSToken_String == mToken.mType)) {
mToken.AppendToString(aSource);
nsAutoString value(mToken.mIdent); nsAutoString value(mToken.mIdent);
if (! GetToken(aErrorCode, PR_FALSE)) { // premature EOF if (! GetToken(aErrorCode, PR_FALSE)) { // premature EOF
return PR_FALSE; return PR_FALSE;
} }
if ((eCSSToken_Symbol == mToken.mType) && (']' == mToken.mSymbol)) { if ((eCSSToken_Symbol == mToken.mType) && (']' == mToken.mSymbol)) {
mToken.AppendToString(aSource);
dataMask |= SEL_MASK_ATTRIB; dataMask |= SEL_MASK_ATTRIB;
if (! mCaseSensitive) { if (! mCaseSensitive) {
value.ToUpperCase(); value.ToUpperCase();

@ -63,6 +63,7 @@ struct SelectorList {
nsCSSSelector* mSelectors; nsCSSSelector* mSelectors;
SelectorList* mNext; SelectorList* mNext;
nsAutoString mSourceString;
}; };
SelectorList::SelectorList(void) SelectorList::SelectorList(void)
@ -148,7 +149,7 @@ protected:
PRBool ParseSelectorList(PRInt32& aErrorCode, SelectorList*& aListHead); PRBool ParseSelectorList(PRInt32& aErrorCode, SelectorList*& aListHead);
PRBool ParseSelectorGroup(PRInt32& aErrorCode, SelectorList*& aListHead); PRBool ParseSelectorGroup(PRInt32& aErrorCode, SelectorList*& aListHead);
PRBool ParseSelector(PRInt32& aErrorCode, nsCSSSelector& aSelectorResult); PRBool ParseSelector(PRInt32& aErrorCode, nsCSSSelector& aSelectorResult, nsString& aSource);
nsICSSDeclaration* ParseDeclarationBlock(PRInt32& aErrorCode, nsICSSDeclaration* ParseDeclarationBlock(PRInt32& aErrorCode,
PRBool aCheckForBraces); PRBool aCheckForBraces);
PRBool ParseDeclaration(PRInt32& aErrorCode, PRBool ParseDeclaration(PRInt32& aErrorCode,
@ -929,6 +930,7 @@ PRBool CSSParserImpl::ParseRuleSet(PRInt32& aErrorCode)
} }
rule->SetDeclaration(declaration); rule->SetDeclaration(declaration);
rule->SetWeight(weight); rule->SetWeight(weight);
rule->SetSourceSelectorText(list->mSourceString); // capture the original input (need this for namespace prefixes)
// rule->List(); // rule->List();
mSheet->AppendStyleRule(rule); mSheet->AppendStyleRule(rule);
NS_RELEASE(rule); NS_RELEASE(rule);
@ -1015,15 +1017,17 @@ static PRBool IsSinglePseudoClass(const nsCSSSelector& aSelector)
PRBool CSSParserImpl::ParseSelectorGroup(PRInt32& aErrorCode, PRBool CSSParserImpl::ParseSelectorGroup(PRInt32& aErrorCode,
SelectorList*& aList) SelectorList*& aList)
{ {
nsAutoString sourceBuffer;
SelectorList* list = nsnull; SelectorList* list = nsnull;
for (;;) { for (;;) {
nsCSSSelector selector; nsCSSSelector selector;
if (! ParseSelector(aErrorCode, selector)) { if (! ParseSelector(aErrorCode, selector, sourceBuffer)) {
break; break;
} }
if (nsnull == list) { if (nsnull == list) {
list = new SelectorList(); list = new SelectorList();
} }
sourceBuffer.Append(PRUnichar(' '));
list->AddSelector(selector); list->AddSelector(selector);
nsCSSSelector* listSel = list->mSelectors; nsCSSSelector* listSel = list->mSelectors;
// XXX parse combinator here // XXX parse combinator here
@ -1060,6 +1064,10 @@ PRBool CSSParserImpl::ParseSelectorGroup(PRInt32& aErrorCode,
} }
} }
aList = list; aList = list;
if (nsnull != list) {
sourceBuffer.Truncate(sourceBuffer.Length() - 1); // kill trailing space
list->mSourceString = sourceBuffer;
}
return PRBool(nsnull != aList); return PRBool(nsnull != aList);
} }
@ -1076,7 +1084,8 @@ PRBool CSSParserImpl::ParseSelectorGroup(PRInt32& aErrorCode,
* operator? [namespace \:]? element_name? [ ID | class | attrib | pseudo ]* * operator? [namespace \:]? element_name? [ ID | class | attrib | pseudo ]*
*/ */
PRBool CSSParserImpl::ParseSelector(PRInt32& aErrorCode, PRBool CSSParserImpl::ParseSelector(PRInt32& aErrorCode,
nsCSSSelector& aSelector) nsCSSSelector& aSelector,
nsString& aSource)
{ {
PRInt32 dataMask = 0; PRInt32 dataMask = 0;
nsAutoString buffer; nsAutoString buffer;
@ -1086,12 +1095,14 @@ PRBool CSSParserImpl::ParseSelector(PRInt32& aErrorCode,
} }
if ((eCSSToken_Symbol == mToken.mType) && ('*' == mToken.mSymbol)) { // universal element selector if ((eCSSToken_Symbol == mToken.mType) && ('*' == mToken.mSymbol)) { // universal element selector
// don't set any tag in the selector // don't set any tag in the selector
mToken.AppendToString(aSource);
dataMask |= SEL_MASK_ELEM; dataMask |= SEL_MASK_ELEM;
if (! GetToken(aErrorCode, PR_FALSE)) { // premature eof is ok (here!) if (! GetToken(aErrorCode, PR_FALSE)) { // premature eof is ok (here!)
return PR_TRUE; return PR_TRUE;
} }
} }
else if (eCSSToken_Ident == mToken.mType) { // element name else if (eCSSToken_Ident == mToken.mType) { // element name
mToken.AppendToString(aSource);
PRInt32 colon = mToken.mIdent.Find(':'); PRInt32 colon = mToken.mIdent.Find(':');
if (-1 == colon) { // no namespace if (-1 == colon) { // no namespace
if (mCaseSensitive) { if (mCaseSensitive) {
@ -1123,6 +1134,7 @@ PRBool CSSParserImpl::ParseSelector(PRInt32& aErrorCode,
if ((0 == (dataMask & SEL_MASK_ID)) && // only one ID if ((0 == (dataMask & SEL_MASK_ID)) && // only one ID
(0 < mToken.mIdent.Length()) && (0 < mToken.mIdent.Length()) &&
(nsString::IsAlpha(mToken.mIdent.CharAt(0)))) { // verify is legal ID (nsString::IsAlpha(mToken.mIdent.CharAt(0)))) { // verify is legal ID
mToken.AppendToString(aSource);
dataMask |= SEL_MASK_ID; dataMask |= SEL_MASK_ID;
aSelector.SetID(mToken.mIdent); aSelector.SetID(mToken.mIdent);
} }
@ -1132,6 +1144,7 @@ PRBool CSSParserImpl::ParseSelector(PRInt32& aErrorCode,
} }
} }
else if ((eCSSToken_Symbol == mToken.mType) && ('.' == mToken.mSymbol)) { // .class else if ((eCSSToken_Symbol == mToken.mType) && ('.' == mToken.mSymbol)) { // .class
mToken.AppendToString(aSource);
if (! GetToken(aErrorCode, PR_FALSE)) { // get ident if (! GetToken(aErrorCode, PR_FALSE)) { // get ident
return PR_FALSE; return PR_FALSE;
} }
@ -1139,6 +1152,7 @@ PRBool CSSParserImpl::ParseSelector(PRInt32& aErrorCode,
UngetToken(); UngetToken();
return PR_FALSE; return PR_FALSE;
} }
mToken.AppendToString(aSource);
dataMask |= SEL_MASK_CLASS; dataMask |= SEL_MASK_CLASS;
if (mCaseSensitive) { if (mCaseSensitive) {
aSelector.AddClass(mToken.mIdent); aSelector.AddClass(mToken.mIdent);
@ -1149,6 +1163,7 @@ PRBool CSSParserImpl::ParseSelector(PRInt32& aErrorCode,
} }
} }
else if ((eCSSToken_Symbol == mToken.mType) && (':' == mToken.mSymbol)) { // :pseudo else if ((eCSSToken_Symbol == mToken.mType) && (':' == mToken.mSymbol)) { // :pseudo
mToken.AppendToString(aSource);
if (! GetToken(aErrorCode, PR_FALSE)) { // premature eof if (! GetToken(aErrorCode, PR_FALSE)) { // premature eof
return PR_FALSE; return PR_FALSE;
} }
@ -1156,6 +1171,7 @@ PRBool CSSParserImpl::ParseSelector(PRInt32& aErrorCode,
UngetToken(); UngetToken();
return PR_FALSE; return PR_FALSE;
} }
mToken.AppendToString(aSource);
buffer.Truncate(); buffer.Truncate();
buffer.Append(':'); buffer.Append(':');
buffer.Append(mToken.mIdent); buffer.Append(mToken.mIdent);
@ -1192,6 +1208,7 @@ PRBool CSSParserImpl::ParseSelector(PRInt32& aErrorCode,
NS_RELEASE(pseudo); NS_RELEASE(pseudo);
} }
else if ((eCSSToken_Symbol == mToken.mType) && ('[' == mToken.mSymbol)) { // attribute else if ((eCSSToken_Symbol == mToken.mType) && ('[' == mToken.mSymbol)) { // attribute
mToken.AppendToString(aSource);
if (! GetToken(aErrorCode, PR_FALSE)) { // premature EOF if (! GetToken(aErrorCode, PR_FALSE)) { // premature EOF
return PR_FALSE; return PR_FALSE;
} }
@ -1199,6 +1216,7 @@ PRBool CSSParserImpl::ParseSelector(PRInt32& aErrorCode,
UngetToken(); UngetToken();
return PR_FALSE; return PR_FALSE;
} }
mToken.AppendToString(aSource);
nsAutoString attr(mToken.mIdent); nsAutoString attr(mToken.mIdent);
if (! mCaseSensitive) { if (! mCaseSensitive) {
attr.ToUpperCase(); attr.ToUpperCase();
@ -1207,6 +1225,7 @@ PRBool CSSParserImpl::ParseSelector(PRInt32& aErrorCode,
return PR_FALSE; return PR_FALSE;
} }
if (eCSSToken_Symbol == mToken.mType) { if (eCSSToken_Symbol == mToken.mType) {
mToken.AppendToString(aSource);
PRUint8 func; PRUint8 func;
if (']' == mToken.mSymbol) { if (']' == mToken.mSymbol) {
dataMask |= SEL_MASK_ATTRIB; dataMask |= SEL_MASK_ATTRIB;
@ -1220,6 +1239,7 @@ PRBool CSSParserImpl::ParseSelector(PRInt32& aErrorCode,
if (! GetToken(aErrorCode, PR_FALSE)) { // premature EOF if (! GetToken(aErrorCode, PR_FALSE)) { // premature EOF
return PR_FALSE; return PR_FALSE;
} }
mToken.AppendToString(aSource);
if ((eCSSToken_Symbol == mToken.mType) && ('=' == mToken.mSymbol)) { if ((eCSSToken_Symbol == mToken.mType) && ('=' == mToken.mSymbol)) {
func = NS_ATTR_FUNC_INCLUDES; func = NS_ATTR_FUNC_INCLUDES;
} }
@ -1232,6 +1252,7 @@ PRBool CSSParserImpl::ParseSelector(PRInt32& aErrorCode,
if (! GetToken(aErrorCode, PR_FALSE)) { // premature EOF if (! GetToken(aErrorCode, PR_FALSE)) { // premature EOF
return PR_FALSE; return PR_FALSE;
} }
mToken.AppendToString(aSource);
if ((eCSSToken_Symbol == mToken.mType) && ('=' == mToken.mSymbol)) { if ((eCSSToken_Symbol == mToken.mType) && ('=' == mToken.mSymbol)) {
func = NS_ATTR_FUNC_DASHMATCH; func = NS_ATTR_FUNC_DASHMATCH;
} }
@ -1249,11 +1270,13 @@ PRBool CSSParserImpl::ParseSelector(PRInt32& aErrorCode,
return PR_FALSE; return PR_FALSE;
} }
if ((eCSSToken_Ident == mToken.mType) || (eCSSToken_String == mToken.mType)) { if ((eCSSToken_Ident == mToken.mType) || (eCSSToken_String == mToken.mType)) {
mToken.AppendToString(aSource);
nsAutoString value(mToken.mIdent); nsAutoString value(mToken.mIdent);
if (! GetToken(aErrorCode, PR_FALSE)) { // premature EOF if (! GetToken(aErrorCode, PR_FALSE)) { // premature EOF
return PR_FALSE; return PR_FALSE;
} }
if ((eCSSToken_Symbol == mToken.mType) && (']' == mToken.mSymbol)) { if ((eCSSToken_Symbol == mToken.mType) && (']' == mToken.mSymbol)) {
mToken.AppendToString(aSource);
dataMask |= SEL_MASK_ATTRIB; dataMask |= SEL_MASK_ATTRIB;
if (! mCaseSensitive) { if (! mCaseSensitive) {
value.ToUpperCase(); value.ToUpperCase();

@ -63,6 +63,7 @@ struct SelectorList {
nsCSSSelector* mSelectors; nsCSSSelector* mSelectors;
SelectorList* mNext; SelectorList* mNext;
nsAutoString mSourceString;
}; };
SelectorList::SelectorList(void) SelectorList::SelectorList(void)
@ -148,7 +149,7 @@ protected:
PRBool ParseSelectorList(PRInt32& aErrorCode, SelectorList*& aListHead); PRBool ParseSelectorList(PRInt32& aErrorCode, SelectorList*& aListHead);
PRBool ParseSelectorGroup(PRInt32& aErrorCode, SelectorList*& aListHead); PRBool ParseSelectorGroup(PRInt32& aErrorCode, SelectorList*& aListHead);
PRBool ParseSelector(PRInt32& aErrorCode, nsCSSSelector& aSelectorResult); PRBool ParseSelector(PRInt32& aErrorCode, nsCSSSelector& aSelectorResult, nsString& aSource);
nsICSSDeclaration* ParseDeclarationBlock(PRInt32& aErrorCode, nsICSSDeclaration* ParseDeclarationBlock(PRInt32& aErrorCode,
PRBool aCheckForBraces); PRBool aCheckForBraces);
PRBool ParseDeclaration(PRInt32& aErrorCode, PRBool ParseDeclaration(PRInt32& aErrorCode,
@ -929,6 +930,7 @@ PRBool CSSParserImpl::ParseRuleSet(PRInt32& aErrorCode)
} }
rule->SetDeclaration(declaration); rule->SetDeclaration(declaration);
rule->SetWeight(weight); rule->SetWeight(weight);
rule->SetSourceSelectorText(list->mSourceString); // capture the original input (need this for namespace prefixes)
// rule->List(); // rule->List();
mSheet->AppendStyleRule(rule); mSheet->AppendStyleRule(rule);
NS_RELEASE(rule); NS_RELEASE(rule);
@ -1015,15 +1017,17 @@ static PRBool IsSinglePseudoClass(const nsCSSSelector& aSelector)
PRBool CSSParserImpl::ParseSelectorGroup(PRInt32& aErrorCode, PRBool CSSParserImpl::ParseSelectorGroup(PRInt32& aErrorCode,
SelectorList*& aList) SelectorList*& aList)
{ {
nsAutoString sourceBuffer;
SelectorList* list = nsnull; SelectorList* list = nsnull;
for (;;) { for (;;) {
nsCSSSelector selector; nsCSSSelector selector;
if (! ParseSelector(aErrorCode, selector)) { if (! ParseSelector(aErrorCode, selector, sourceBuffer)) {
break; break;
} }
if (nsnull == list) { if (nsnull == list) {
list = new SelectorList(); list = new SelectorList();
} }
sourceBuffer.Append(PRUnichar(' '));
list->AddSelector(selector); list->AddSelector(selector);
nsCSSSelector* listSel = list->mSelectors; nsCSSSelector* listSel = list->mSelectors;
// XXX parse combinator here // XXX parse combinator here
@ -1060,6 +1064,10 @@ PRBool CSSParserImpl::ParseSelectorGroup(PRInt32& aErrorCode,
} }
} }
aList = list; aList = list;
if (nsnull != list) {
sourceBuffer.Truncate(sourceBuffer.Length() - 1); // kill trailing space
list->mSourceString = sourceBuffer;
}
return PRBool(nsnull != aList); return PRBool(nsnull != aList);
} }
@ -1076,7 +1084,8 @@ PRBool CSSParserImpl::ParseSelectorGroup(PRInt32& aErrorCode,
* operator? [namespace \:]? element_name? [ ID | class | attrib | pseudo ]* * operator? [namespace \:]? element_name? [ ID | class | attrib | pseudo ]*
*/ */
PRBool CSSParserImpl::ParseSelector(PRInt32& aErrorCode, PRBool CSSParserImpl::ParseSelector(PRInt32& aErrorCode,
nsCSSSelector& aSelector) nsCSSSelector& aSelector,
nsString& aSource)
{ {
PRInt32 dataMask = 0; PRInt32 dataMask = 0;
nsAutoString buffer; nsAutoString buffer;
@ -1086,12 +1095,14 @@ PRBool CSSParserImpl::ParseSelector(PRInt32& aErrorCode,
} }
if ((eCSSToken_Symbol == mToken.mType) && ('*' == mToken.mSymbol)) { // universal element selector if ((eCSSToken_Symbol == mToken.mType) && ('*' == mToken.mSymbol)) { // universal element selector
// don't set any tag in the selector // don't set any tag in the selector
mToken.AppendToString(aSource);
dataMask |= SEL_MASK_ELEM; dataMask |= SEL_MASK_ELEM;
if (! GetToken(aErrorCode, PR_FALSE)) { // premature eof is ok (here!) if (! GetToken(aErrorCode, PR_FALSE)) { // premature eof is ok (here!)
return PR_TRUE; return PR_TRUE;
} }
} }
else if (eCSSToken_Ident == mToken.mType) { // element name else if (eCSSToken_Ident == mToken.mType) { // element name
mToken.AppendToString(aSource);
PRInt32 colon = mToken.mIdent.Find(':'); PRInt32 colon = mToken.mIdent.Find(':');
if (-1 == colon) { // no namespace if (-1 == colon) { // no namespace
if (mCaseSensitive) { if (mCaseSensitive) {
@ -1123,6 +1134,7 @@ PRBool CSSParserImpl::ParseSelector(PRInt32& aErrorCode,
if ((0 == (dataMask & SEL_MASK_ID)) && // only one ID if ((0 == (dataMask & SEL_MASK_ID)) && // only one ID
(0 < mToken.mIdent.Length()) && (0 < mToken.mIdent.Length()) &&
(nsString::IsAlpha(mToken.mIdent.CharAt(0)))) { // verify is legal ID (nsString::IsAlpha(mToken.mIdent.CharAt(0)))) { // verify is legal ID
mToken.AppendToString(aSource);
dataMask |= SEL_MASK_ID; dataMask |= SEL_MASK_ID;
aSelector.SetID(mToken.mIdent); aSelector.SetID(mToken.mIdent);
} }
@ -1132,6 +1144,7 @@ PRBool CSSParserImpl::ParseSelector(PRInt32& aErrorCode,
} }
} }
else if ((eCSSToken_Symbol == mToken.mType) && ('.' == mToken.mSymbol)) { // .class else if ((eCSSToken_Symbol == mToken.mType) && ('.' == mToken.mSymbol)) { // .class
mToken.AppendToString(aSource);
if (! GetToken(aErrorCode, PR_FALSE)) { // get ident if (! GetToken(aErrorCode, PR_FALSE)) { // get ident
return PR_FALSE; return PR_FALSE;
} }
@ -1139,6 +1152,7 @@ PRBool CSSParserImpl::ParseSelector(PRInt32& aErrorCode,
UngetToken(); UngetToken();
return PR_FALSE; return PR_FALSE;
} }
mToken.AppendToString(aSource);
dataMask |= SEL_MASK_CLASS; dataMask |= SEL_MASK_CLASS;
if (mCaseSensitive) { if (mCaseSensitive) {
aSelector.AddClass(mToken.mIdent); aSelector.AddClass(mToken.mIdent);
@ -1149,6 +1163,7 @@ PRBool CSSParserImpl::ParseSelector(PRInt32& aErrorCode,
} }
} }
else if ((eCSSToken_Symbol == mToken.mType) && (':' == mToken.mSymbol)) { // :pseudo else if ((eCSSToken_Symbol == mToken.mType) && (':' == mToken.mSymbol)) { // :pseudo
mToken.AppendToString(aSource);
if (! GetToken(aErrorCode, PR_FALSE)) { // premature eof if (! GetToken(aErrorCode, PR_FALSE)) { // premature eof
return PR_FALSE; return PR_FALSE;
} }
@ -1156,6 +1171,7 @@ PRBool CSSParserImpl::ParseSelector(PRInt32& aErrorCode,
UngetToken(); UngetToken();
return PR_FALSE; return PR_FALSE;
} }
mToken.AppendToString(aSource);
buffer.Truncate(); buffer.Truncate();
buffer.Append(':'); buffer.Append(':');
buffer.Append(mToken.mIdent); buffer.Append(mToken.mIdent);
@ -1192,6 +1208,7 @@ PRBool CSSParserImpl::ParseSelector(PRInt32& aErrorCode,
NS_RELEASE(pseudo); NS_RELEASE(pseudo);
} }
else if ((eCSSToken_Symbol == mToken.mType) && ('[' == mToken.mSymbol)) { // attribute else if ((eCSSToken_Symbol == mToken.mType) && ('[' == mToken.mSymbol)) { // attribute
mToken.AppendToString(aSource);
if (! GetToken(aErrorCode, PR_FALSE)) { // premature EOF if (! GetToken(aErrorCode, PR_FALSE)) { // premature EOF
return PR_FALSE; return PR_FALSE;
} }
@ -1199,6 +1216,7 @@ PRBool CSSParserImpl::ParseSelector(PRInt32& aErrorCode,
UngetToken(); UngetToken();
return PR_FALSE; return PR_FALSE;
} }
mToken.AppendToString(aSource);
nsAutoString attr(mToken.mIdent); nsAutoString attr(mToken.mIdent);
if (! mCaseSensitive) { if (! mCaseSensitive) {
attr.ToUpperCase(); attr.ToUpperCase();
@ -1207,6 +1225,7 @@ PRBool CSSParserImpl::ParseSelector(PRInt32& aErrorCode,
return PR_FALSE; return PR_FALSE;
} }
if (eCSSToken_Symbol == mToken.mType) { if (eCSSToken_Symbol == mToken.mType) {
mToken.AppendToString(aSource);
PRUint8 func; PRUint8 func;
if (']' == mToken.mSymbol) { if (']' == mToken.mSymbol) {
dataMask |= SEL_MASK_ATTRIB; dataMask |= SEL_MASK_ATTRIB;
@ -1220,6 +1239,7 @@ PRBool CSSParserImpl::ParseSelector(PRInt32& aErrorCode,
if (! GetToken(aErrorCode, PR_FALSE)) { // premature EOF if (! GetToken(aErrorCode, PR_FALSE)) { // premature EOF
return PR_FALSE; return PR_FALSE;
} }
mToken.AppendToString(aSource);
if ((eCSSToken_Symbol == mToken.mType) && ('=' == mToken.mSymbol)) { if ((eCSSToken_Symbol == mToken.mType) && ('=' == mToken.mSymbol)) {
func = NS_ATTR_FUNC_INCLUDES; func = NS_ATTR_FUNC_INCLUDES;
} }
@ -1232,6 +1252,7 @@ PRBool CSSParserImpl::ParseSelector(PRInt32& aErrorCode,
if (! GetToken(aErrorCode, PR_FALSE)) { // premature EOF if (! GetToken(aErrorCode, PR_FALSE)) { // premature EOF
return PR_FALSE; return PR_FALSE;
} }
mToken.AppendToString(aSource);
if ((eCSSToken_Symbol == mToken.mType) && ('=' == mToken.mSymbol)) { if ((eCSSToken_Symbol == mToken.mType) && ('=' == mToken.mSymbol)) {
func = NS_ATTR_FUNC_DASHMATCH; func = NS_ATTR_FUNC_DASHMATCH;
} }
@ -1249,11 +1270,13 @@ PRBool CSSParserImpl::ParseSelector(PRInt32& aErrorCode,
return PR_FALSE; return PR_FALSE;
} }
if ((eCSSToken_Ident == mToken.mType) || (eCSSToken_String == mToken.mType)) { if ((eCSSToken_Ident == mToken.mType) || (eCSSToken_String == mToken.mType)) {
mToken.AppendToString(aSource);
nsAutoString value(mToken.mIdent); nsAutoString value(mToken.mIdent);
if (! GetToken(aErrorCode, PR_FALSE)) { // premature EOF if (! GetToken(aErrorCode, PR_FALSE)) { // premature EOF
return PR_FALSE; return PR_FALSE;
} }
if ((eCSSToken_Symbol == mToken.mType) && (']' == mToken.mSymbol)) { if ((eCSSToken_Symbol == mToken.mType) && (']' == mToken.mSymbol)) {
mToken.AppendToString(aSource);
dataMask |= SEL_MASK_ATTRIB; dataMask |= SEL_MASK_ATTRIB;
if (! mCaseSensitive) { if (! mCaseSensitive) {
value.ToUpperCase(); value.ToUpperCase();