From 2e50ebe6fb3ece6c33d648ca3e222524d79c3999 Mon Sep 17 00:00:00 2001 From: Michael Drake Date: Wed, 1 Aug 2018 15:38:49 +0100 Subject: HACKS for testing Media Queries parsing. Top level stylesheets need to have their media query passed in. So we need a way to parse standalone media queries. This was hacked together to explore doing that. However, it encounteded an issue where it seems the parseAtRule() function in src/parse/parse.c doesn't handle the full grammar for media queries. --- src/parse/language.c | 1 - src/parse/parse.c | 23 +++++++++- src/parse/parse.h | 2 + src/stylesheet.c | 118 +++++++++++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 141 insertions(+), 3 deletions(-) diff --git a/src/parse/language.c b/src/parse/language.c index faafcfd..54fac9a 100644 --- a/src/parse/language.c +++ b/src/parse/language.c @@ -532,7 +532,6 @@ css_error handleStartAtRule(css_language *c, const parserutils_vector *vector) css_mq_query *media = NULL; /* any0 = media query */ - error = css__mq_parse_media_list( c->strings, vector, &ctx, &media); if (error != CSS_OK) diff --git a/src/parse/parse.c b/src/parse/parse.c index 4cc1c98..f02526b 100644 --- a/src/parse/parse.c +++ b/src/parse/parse.c @@ -219,6 +219,25 @@ css_error css__parser_create_for_inline_style(const char *charset, initial, parser); } +/** + * Create a CSS parser for a media query + * + * \param charset Charset of data, if known, or NULL + * \param cs_source Source of charset information, or CSS_CHARSET_DEFAULT + * \param parser Pointer to location to receive parser instance + * \return CSS_OK on success, + * CSS_BADPARM on bad parameters, + * CSS_NOMEM on memory exhaustion + */ +css_error css__parser_create_for_media_query(const char *charset, + css_charset_source cs_source, css_parser **parser) +{ + parser_state initial = { sAtRule, 0 }; + + return css__parser_create_internal(charset, cs_source, + initial, parser); +} + /** * Destroy a CSS parser * @@ -1061,7 +1080,7 @@ css_error parseAtRule(css_parser *parser) /* Fall through */ case Any: { - parser_state to = { sAny0, Initial }; + parser_state to = { sAny, Initial }; parser_state subsequent = { sAtRule, AfterAny }; return transition(parser, to, subsequent); @@ -1084,7 +1103,7 @@ css_error parseAtRule(css_parser *parser) if (lwc_string_data(token->idata)[0] == ')' || lwc_string_data( token->idata)[0] == ']') { - parser_state to = { sAny0, Initial }; + parser_state to = { sAny, Initial }; parser_state subsequent = { sAtRule, AfterAny }; return transition(parser, to, subsequent); diff --git a/src/parse/parse.h b/src/parse/parse.h index 833aa51..e65f055 100644 --- a/src/parse/parse.h +++ b/src/parse/parse.h @@ -61,6 +61,8 @@ css_error css__parser_create(const char *charset, css_charset_source cs_source, css_parser **parser); css_error css__parser_create_for_inline_style(const char *charset, css_charset_source cs_source, css_parser **parser); +css_error css__parser_create_for_media_query(const char *charset, + css_charset_source cs_source, css_parser **parser); css_error css__parser_destroy(css_parser *parser); css_error css__parser_setopt(css_parser *parser, css_parser_opttype type, diff --git a/src/stylesheet.c b/src/stylesheet.c index 22c7681..1ee9eed 100644 --- a/src/stylesheet.c +++ b/src/stylesheet.c @@ -113,6 +113,121 @@ css_error css__stylesheet_string_get(css_stylesheet *sheet, return CSS_OK; } +static css_error css_parse_media_query_handle_event(css_parser_event type, + const parserutils_vector *tokens, void *pw) +{ + int idx = 0; + css_error err; + css_mq_query *media; + const css_token *tok; + lwc_string **strings = pw; + + printf("mq event type: %i\n", type); + + /* Skip @media */ + tok = parserutils_vector_iterate(tokens, &idx); + assert(tok->type == CSS_TOKEN_ATKEYWORD); + UNUSED(tok); + + /* Skip whitespace */ + tok = parserutils_vector_iterate(tokens, &idx); + assert(tok->type == CSS_TOKEN_S); + UNUSED(tok); + + printf(" Tokens:\n"); + while ((tok = parserutils_vector_iterate(tokens, &idx)) != NULL) { + if (tok->idata != NULL) { + printf(" - (%i) %s\n", + tok->type, + lwc_string_data(tok->idata)); + } else { + printf(" - (%i)\n", tok->type); + } + } + idx = 2; + + err = css__mq_parse_media_list(strings, tokens, &idx, &media); + if (err != CSS_OK) { + printf("Error parsing mq\n"); + return CSS_OK; + } + + printf("PARSED MQ!!!!!!!\n"); + css__mq_query_destroy(media); + + return CSS_OK; +} + +static css_error css_parse_media_query(lwc_string **strings, + const uint8_t *mq, size_t len) +{ + css_error err; + css_parser *parser; + css_parser_optparams params_quirks = { + .quirks = false, + }; + css_parser_optparams params_handler = { + .event_handler = { + .handler = css_parse_media_query_handle_event, + .pw = strings, + }, + }; + + err = css__parser_create_for_media_query(NULL, + CSS_CHARSET_DEFAULT, &parser); + if (err != CSS_OK) { + return err; + } + + err = css__parser_setopt(parser, CSS_PARSER_QUIRKS, + ¶ms_quirks); + if (err != CSS_OK) { + css__parser_destroy(parser); + return err; + } + + err = css__parser_setopt(parser, CSS_PARSER_EVENT_HANDLER, + ¶ms_handler); + if (err != CSS_OK) { + css__parser_destroy(parser); + return err; + } + + printf("try parsing a mq\n"); + err = css__parser_parse_chunk(parser, + (const uint8_t *)"@media ", + strlen("@media ")); + if (err != CSS_OK && err != CSS_NEEDDATA) { + css__parser_destroy(parser); + return err; + } + + err = css__parser_parse_chunk(parser, mq, len); + if (err != CSS_OK && err != CSS_NEEDDATA) { + css__parser_destroy(parser); + return err; + } + + err = css__parser_parse_chunk(parser, + (const uint8_t *)" {", + strlen(" {")); + if (err != CSS_OK && err != CSS_NEEDDATA) { + css__parser_destroy(parser); + return err; + } + + err = css__parser_completed(parser); + if (err != CSS_OK) { + css__parser_destroy(parser); + return err; + } + + css__parser_destroy(parser); + + return CSS_OK; +} + + /** * Create a stylesheet * @@ -144,6 +259,9 @@ css_error css_stylesheet_create(const css_stylesheet_params *params, free(sheet); return error; } +css_parse_media_query(sheet->propstrings, + (const uint8_t *)"screen and (min-width: 30em)", + strlen("screen and (min-width: 30em)")); sheet->inline_style = params->inline_style; -- cgit v1.2.1