diff options
Diffstat (limited to 'css')
-rw-r--r-- | css/css.c | 78 | ||||
-rw-r--r-- | css/css.h | 6 | ||||
-rw-r--r-- | css/parser.y | 42 | ||||
-rw-r--r-- | css/scanner.l | 3 |
4 files changed, 129 insertions, 0 deletions
@@ -870,6 +870,69 @@ bool css_match_detail(const struct css_selector *detail, match = true; break; + case CSS_SELECTOR_ATTRIB_PRE: + /* matches if the attribute begins with a certain + * value (CSS3) */ + word = strndup(detail->data, detail->data_length); + if (!word) { + /** \todo report to user */ + return false; + } + s = (char *)xmlGetProp(element, + (const xmlChar *) word); + free(word); + if (s && strncasecmp(detail->data2, s, + detail->data2_length) == 0) + match = true; + break; + + case CSS_SELECTOR_ATTRIB_SUF: + /* matches if the attribute ends with a certain + * value (CSS3) */ + word = strndup(detail->data, detail->data_length); + if (!word) { + /** \todo report to user */ + return false; + } + s = (char *)xmlGetProp(element, + (const xmlChar *) word); + free(word); + if (!s) + break; + word = s + (strlen(s) - detail->data2_length); + if (s && strncasecmp(detail->data2, word, + detail->data2_length) == 0) + match = true; + break; + + case CSS_SELECTOR_ATTRIB_SUB: + /* matches if the attribute contains a certain + * value (CSS3) */ + word = strndup(detail->data, detail->data_length); + if (!word) { + /** \todo report to user */ + return false; + } + s = (char *)xmlGetProp(element, + (const xmlChar *) word); + free(word); + if (!s) + break; + /* case insensitive strstr follows */ + /* space -> last possible start position */ + /* word -> start of string to search */ + space = s + (strlen(s) - detail->data2_length); + word = s; + while (word <= space) { + if (strncasecmp(detail->data2, word, + detail->data2_length) == 0) { + match = true; + break; + } + word++; + } + break; + case CSS_SELECTOR_PSEUDO: break; @@ -1336,6 +1399,21 @@ void css_dump_selector(const struct css_selector *r) m->data_length, m->data, m->data2_length, m->data2); break; + case CSS_SELECTOR_ATTRIB_PRE: + fprintf(stderr, "[%.*s^=%.*s]", + m->data_length, m->data, + m->data2_length, m->data2); + break; + case CSS_SELECTOR_ATTRIB_SUF: + fprintf(stderr, "[%.*s$=%.*s]", + m->data_length, m->data, + m->data2_length, m->data2); + break; + case CSS_SELECTOR_ATTRIB_SUB: + fprintf(stderr, "[%.*s*=%.*s]", + m->data_length, m->data, + m->data2_length, m->data2); + break; case CSS_SELECTOR_PSEUDO: fprintf(stderr, ":%.*s", m->data_length, m->data); @@ -222,6 +222,9 @@ typedef enum { CSS_SELECTOR_ATTRIB_EQ, CSS_SELECTOR_ATTRIB_INC, CSS_SELECTOR_ATTRIB_DM, + CSS_SELECTOR_ATTRIB_PRE, + CSS_SELECTOR_ATTRIB_SUF, + CSS_SELECTOR_ATTRIB_SUB, CSS_SELECTOR_PSEUDO, } css_selector_type; @@ -263,6 +266,9 @@ typedef enum { CSS_NODE_INCLUDES, CSS_NODE_FUNCTION, CSS_NODE_DASHMATCH, + CSS_NODE_PREFIX, + CSS_NODE_SUFFIX, + CSS_NODE_SUBSTR, CSS_NODE_COLON, CSS_NODE_COMMA, CSS_NODE_DOT, diff --git a/css/parser.y b/css/parser.y index 1dd567ff1..f043ef823 100644 --- a/css/parser.y +++ b/css/parser.y @@ -185,6 +185,36 @@ detail(A) ::= LBRAC IDENT(B) DASHMATCH STRING(C) RBRAC. if (A) { A->data2 = C.text + 1; A->data2_length = C.length - 2; A->specificity = 0x100; } else param->memory_error = true; } +detail(A) ::= LBRAC IDENT(B) PREFIX IDENT(C) RBRAC. + { A = css_new_selector(CSS_SELECTOR_ATTRIB_PRE, B.text, B.length); + if (A) { A->data2 = C.text; A->data2_length = C.length; + A->specificity = 0x100; } + else param->memory_error = true; } +detail(A) ::= LBRAC IDENT(B) PREFIX STRING(C) RBRAC. + { A = css_new_selector(CSS_SELECTOR_ATTRIB_PRE, B.text, B.length); + if (A) { A->data2 = C.text + 1; A->data2_length = C.length - 2; + A->specificity = 0x100; } + else param->memory_error = true; } +detail(A) ::= LBRAC IDENT(B) SUFFIX IDENT(C) RBRAC. + { A = css_new_selector(CSS_SELECTOR_ATTRIB_SUF, B.text, B.length); + if (A) { A->data2 = C.text; A->data2_length = C.length; + A->specificity = 0x100; } + else param->memory_error = true; } +detail(A) ::= LBRAC IDENT(B) SUFFIX STRING(C) RBRAC. + { A = css_new_selector(CSS_SELECTOR_ATTRIB_SUF, B.text, B.length); + if (A) { A->data2 = C.text + 1; A->data2_length = C.length - 2; + A->specificity = 0x100; } + else param->memory_error = true; } +detail(A) ::= LBRAC IDENT(B) SUBSTR IDENT(C) RBRAC. + { A = css_new_selector(CSS_SELECTOR_ATTRIB_SUB, B.text, B.length); + if (A) { A->data2 = C.text; A->data2_length = C.length; + A->specificity = 0x100; } + else param->memory_error = true; } +detail(A) ::= LBRAC IDENT(B) SUBSTR STRING(C) RBRAC. + { A = css_new_selector(CSS_SELECTOR_ATTRIB_SUB, B.text, B.length); + if (A) { A->data2 = C.text + 1; A->data2_length = C.length - 2; + A->specificity = 0x100; } + else param->memory_error = true; } detail(A) ::= COLON IDENT(B). { if (B.length == 4 && strncasecmp(B.text, "link", 4) == 0) { A = css_new_selector(CSS_SELECTOR_ATTRIB, "href", 4); @@ -297,6 +327,18 @@ any(A) ::= DASHMATCH. { A = css_new_node(param->stylesheet, CSS_NODE_DASHMATCH, 0, 0); if (!A) param->memory_error = true; } +any(A) ::= PREFIX. + { A = css_new_node(param->stylesheet, CSS_NODE_PREFIX, + 0, 0); + if (!A) param->memory_error = true; } +any(A) ::= SUFFIX. + { A = css_new_node(param->stylesheet, CSS_NODE_SUFFIX, + 0, 0); + if (!A) param->memory_error = true; } +any(A) ::= SUBSTR. + { A = css_new_node(param->stylesheet, CSS_NODE_SUBSTR, + 0, 0); + if (!A) param->memory_error = true; } any(A) ::= COLON. { A = css_new_node(param->stylesheet, CSS_NODE_COLON, 0, 0); if (!A) param->memory_error = true; } diff --git a/css/scanner.l b/css/scanner.l index 36347b3a8..708a9ebe8 100644 --- a/css/scanner.l +++ b/css/scanner.l @@ -86,6 +86,9 @@ ident "(" { return FUNCTION; } "=" { return EQUALS; } "~=" { return INCLUDES; } "|=" { return DASHMATCH; } +"^=" { return PREFIX; } +"$=" { return SUFFIX; } +"*=" { return SUBSTR; } ":" { return COLON; } "," { return COMMA; } "+" { return PLUS; } |