Skip to content

Commit

Permalink
Fix a few CSS selector issues (#178)
Browse files Browse the repository at this point in the history
- fix standalone #ID (was working only as ELEM#ID)
- fix non-lowercase element name (elements are internally
  lowercased, so we should lowercase there too to expect any match)
- fix E+F selector, that should ignore immediate preceding text
  nodes, and consider the first met element node
- adds E~F selector (like E+F, but *any* instead of "immediate"
  precedessor is considered for a match)
  • Loading branch information
poire-z authored May 5, 2018
1 parent 30a40cf commit 5cd06ec
Show file tree
Hide file tree
Showing 2 changed files with 31 additions and 7 deletions.
1 change: 1 addition & 0 deletions crengine/include/lvstsheet.h
Original file line number Diff line number Diff line change
Expand Up @@ -94,6 +94,7 @@ enum LVCssSelectorRuleType
cssrt_parent, // E > F
cssrt_ancessor, // E F
cssrt_predecessor, // E + F
cssrt_predsibling, // E ~ F
cssrt_attrset, // E[foo]
cssrt_attreq, // E[foo="value"]
cssrt_attrhas, // E[foo~="value"]
Expand Down
37 changes: 30 additions & 7 deletions crengine/src/lvstsheet.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1989,6 +1989,7 @@ lUInt32 LVCssSelectorRule::getWeight() {
case cssrt_parent: // E > F
case cssrt_ancessor: // E F
case cssrt_predecessor: // E + F
case cssrt_predsibling: // E ~ F
return 1;
break;
case cssrt_universal: // *
Expand Down Expand Up @@ -2029,18 +2030,26 @@ bool LVCssSelectorRule::check( const ldomNode * & node )
}
break;
case cssrt_predecessor: // E + F
case cssrt_predsibling: // E ~ F (preceding sibling)
//
{
int index = node->getNodeIndex();
// while
if (index>0) {
ldomNode * elem = node->getParentNode()->getChildElementNode(index-1, _id);
if ( elem ) {
node = elem;
//CRLog::trace("+ selector: found pred element");
return true;
ldomNode * parent = node->getParentNode();
for (int i=index-1; i>=0; i--) {
ldomNode * elem = parent->getChildElementNode(i);
// we get NULL when a child is a text node, that we should ignore
if ( elem ) { // this is an element node
if (elem->getNodeId() == _id) {
node = elem;
return true;
}
if (_type == cssrt_predecessor) {
return false;
}
}
}
//index--;
}
return false;
}
Expand Down Expand Up @@ -2296,13 +2305,17 @@ bool LVCssSelector::parse( const char * &str, lxmlDocBase * doc )
{
_id = 0;
}
else if ( *str == '#' ) // node Id follows
{
_id = 0; // (elementName internal id)
}
else if ( css_is_alpha( *str ) )
{
// ident
char ident[64];
if (!parse_ident( str, ident ))
return false;
_id = doc->getElementNameIndex( lString16(ident).c_str() );
_id = doc->getElementNameIndex( lString16(ident).lowercase().c_str() );
_specificity += 1; // we have an element: this adds 1 to specificity
skip_spaces( str );
}
Expand Down Expand Up @@ -2357,6 +2370,16 @@ bool LVCssSelector::parse( const char * &str, lxmlDocBase * doc )
_id=0;
continue;
}
else if (*str == '~')
{
str++;
LVCssSelectorRule * rule = new LVCssSelectorRule(cssrt_predsibling);
rule->setId(_id);
insertRuleStart( rule );
_specificity += rule->getWeight();
_id=0;
continue;
}
else if (css_is_alpha( *str ))
{
LVCssSelectorRule * rule = new LVCssSelectorRule(cssrt_ancessor);
Expand Down

0 comments on commit 5cd06ec

Please sign in to comment.