From e4392a5113c90aacc3abf4bd066ebbc3e000171f Mon Sep 17 00:00:00 2001 From: Danny van Kooten Date: Wed, 18 Mar 2020 16:10:50 +0100 Subject: add tests for whitespace control --- src/template.c | 31 +++++++++++++++++--- tests/test_template.c | 78 +++++++++++++++++++++++++++++++++++++++++++++------ 2 files changed, 97 insertions(+), 12 deletions(-) diff --git a/src/template.c b/src/template.c index 4a893b8..7ea4d05 100644 --- a/src/template.c +++ b/src/template.c @@ -82,7 +82,7 @@ mpc_parser_t *parser_init() { template = mpc_new("template"); mpca_lang(MPCA_LANG_WHITESPACE_SENSITIVE, - " spaces : (' ')*;" + " spaces : / */ ;" " symbol : /[a-zA-Z][a-zA-Z0-9_.]*/ ;" " number : /[0-9]+/ ;" " text : /[^{][^{%#]*/;" @@ -90,7 +90,7 @@ mpc_parser_t *parser_init() { " op : '+' | '-' | '*' | '/' | '>' | '<';" " expression: ( | | ) ( ( | | ))* ;" " print : (/{{2}-? */) / *-?}}/ ;" - " comment : \"{#\" /[^#][^#}]*/ \"#}\" ;" + " comment : \"{#\" /[^#][^#}]*/ \"#}\" ;" " statement_open: /{\%-? */;" " statement_close: / *-?\%}/;" " for : \"for \" \" in \" \"endfor\" ;" @@ -422,27 +422,50 @@ int eval(struct buffer *buf, mpc_ast_t* t, struct context *ctx) { } if (strstr(t->tag, "content|statement|for")) { - trim_whitespace = strstr(t->children[5]->contents, "-") ? 1 : 0; char *tmp_key = t->children[2]->contents; char *iterator_key = t->children[4]->contents; struct vector *list = hashmap_resolve(ctx->vars, iterator_key); for (int i=0; i < list->size; i++) { hashmap_insert(ctx->vars, tmp_key, list->values[i]); + trim_whitespace = strstr(t->children[5]->contents, "-") ? 1 : 0; eval(buf, t->children[6], ctx); } + + /* trim trailing whitespace if closing tag has minus sign */ + if (strstr(t->children[7]->contents, "-")) { + buf->string = trim_trailing_whitespace(buf->string); + } + + trim_whitespace = strstr(t->children[9]->contents, "-") ? 1 : 0; return 0; } if (strstr(t->tag, "content|statement|if")) { - trim_whitespace = strstr(t->children[3]->contents, "-") ? 1 : 0; mpc_ast_t *expr = t->children[2]; struct unja_object *result = eval_expression(expr, ctx); if (object_is_truthy(result)) { + trim_whitespace = strstr(t->children[3]->contents, "-") ? 1 : 0; + eval(buf, t->children[4], ctx); + + /* trim trailing whitespace if closing tag has minus sign */ + if (strstr(t->children[5]->contents, "-")) { + buf->string = trim_trailing_whitespace(buf->string); + } + + trim_whitespace = strstr(t->children[7]->contents, "-") ? 1 : 0; } else { if (t->children_num > 8) { + trim_whitespace = strstr(t->children[7]->contents, "-") ? 1 : 0; eval(buf, t->children[8], ctx); + + /* trim trailing whitespace if closing tag has minus sign */ + if (strstr(t->children[9]->contents, "-")) { + buf->string = trim_trailing_whitespace(buf->string); + } + + trim_whitespace = strstr(t->children[11]->contents, "-") ? 1 : 0; } } diff --git a/tests/test_template.c b/tests/test_template.c index 244e788..34022fa 100644 --- a/tests/test_template.c +++ b/tests/test_template.c @@ -17,6 +17,13 @@ TEST(expr_number) { free(output); } +TEST(expr_number_no_spaces) { + char *input = "Hello {{5}}."; + char *output = template_string(input, NULL); + assert_str(output, "Hello 5."); + free(output); +} + TEST(expr_string) { char *input = "Hello {{ \"world\" }}."; char *output = template_string(input, NULL); @@ -24,7 +31,24 @@ TEST(expr_string) { free(output); } +TEST(expr_string_no_spaces) { + char *input = "Hello {{\"world\"}}."; + char *output = template_string(input, NULL); + assert_str(output, "Hello world."); + free(output); +} + TEST(expr_symbol) { + char *input = "Hello {{ name }}."; + struct hashmap *ctx = hashmap_new(); + hashmap_insert(ctx, "name", "world"); + char *output = template_string(input, ctx); + assert_str(output, "Hello world."); + hashmap_free(ctx); + free(output); +} + +TEST(expr_symbol_no_spaces) { char *input = "Hello {{name}}."; struct hashmap *ctx = hashmap_new(); hashmap_insert(ctx, "name", "world"); @@ -43,6 +67,12 @@ TEST(expr_add) { {"{{ 5 + foo }}.", "15."}, {"{{ \"foo\" + \"bar\" }}", "foobar"}, {"{{ \"Hello \" + name }}", "Hello Danny"}, + {"{{5+5}}", "10"}, + {"{{ 5+5}}", "10"}, + {"{{ 5 +5}}", "10"}, + {"{{ 5 +5}}", "10"}, + {"{{ 5 + 5}}", "10"}, + {"{{ 5 + 5 }}", "10"}, }; struct hashmap *ctx = hashmap_new(); @@ -104,12 +134,16 @@ TEST(expr_lt) { } TEST(expr_whitespace) { - char *input = "Hello \n{{-name -}}\n."; - struct hashmap *ctx = hashmap_new(); - hashmap_insert(ctx, "name", "world"); - char *output = template_string(input, ctx); + char *input = "Hello \n{{- \"world\" -}}\n."; + char *output = template_string(input, NULL); assert_str(output, "Helloworld."); - hashmap_free(ctx); + free(output); +} + +TEST(expr_op_whitespace) { + char *input = "\n{{- 5 + 5 -}}\n"; + char *output = template_string(input, NULL); + assert_str(output, "10"); free(output); } @@ -130,6 +164,22 @@ TEST(for_block) { free(output); } +TEST(for_block_whitespace) { + char *input = "\n{%- for n in names -%}\n{{ n }}\n{%- endfor -%}\n"; + struct hashmap *ctx = hashmap_new(); + + struct vector *names = vector_new(2); + vector_push(names, "John"); + vector_push(names, "Sally"); + hashmap_insert(ctx, "names", names); + + char *output = template_string(input, ctx); + assert_str(output, "John\nSally"); + vector_free(names); + hashmap_free(ctx); + free(output); +} + TEST(var_dot_notation) { char *input = "Hello {{user.name}}!"; struct hashmap *user = hashmap_new(); @@ -144,7 +194,7 @@ TEST(var_dot_notation) { free(output); } -TEST(comments) { +TEST(comment) { char *input = "Hello {# comment here #}world."; char *output = template_string(input, NULL); assert_str(output, "Hello world."); @@ -152,7 +202,6 @@ TEST(comments) { } TEST(if_block) { - struct { char *input; char *expected_output; @@ -176,8 +225,14 @@ TEST(if_block) { hashmap_free(ctx); } -TEST(if_else_block) { +TEST(if_block_whitespace) { + char *input = "\n{%- if 10 > 5 -%}\nOK\n{%- endif -%}\n"; + char *output = template_string(input, NULL); + assert_str(output, "OK"); + free(output); +} +TEST(if_else_block) { struct { char *input; char *expected_output; @@ -201,6 +256,13 @@ TEST(if_else_block) { hashmap_free(ctx); } +TEST(if_else_block_whitespace) { + char *input = "\n{%- if 5 > 10 -%}NOT OK{% else -%}\nOK\n{%- endif -%}\n"; + char *output = template_string(input, NULL); + assert_str(output, "OK"); + free(output); +} + TEST(buffer_alloc) { /* Output a string so that output buffer is longer than template buffer, to test dynamic allocation */ -- cgit v1.2.3