aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/template.c31
-rw-r--r--tests/test_template.c78
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: (<symbol> | <number> | <string>) (<spaces> <op> <spaces> (<symbol> | <number> | <string>))* ;"
" print : (/{{2}-? */) <expression> / *-?}}/ ;"
- " comment : \"{#\" /[^#][^#}]*/ \"#}\" ;"
+ " comment : \"{#\" /[^#][^#}]*/ \"#}\" ;"
" statement_open: /{\%-? */;"
" statement_close: / *-?\%}/;"
" for : <statement_open> \"for \" <symbol> \" in \" <symbol> <statement_close> <body> <statement_open> \"endfor\" <statement_close> ;"
@@ -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 */