aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorRafael G. Martins <rafael@rafaelmartins.eng.br>2016-05-29 14:19:54 +0200
committerRafael G. Martins <rafael@rafaelmartins.eng.br>2016-05-30 01:17:19 +0200
commitfabdcfe3f7dc890f89c0ca2f0ef034d189226531 (patch)
treec3f831a3b60c79dbb9cdca626f9d649be07af557
parent407c8e7ba58755a2f0998e46b594d89aff4ec7d6 (diff)
downloadblogc-fabdcfe3f7dc890f89c0ca2f0ef034d189226531.tar.gz
blogc-fabdcfe3f7dc890f89c0ca2f0ef034d189226531.tar.bz2
blogc-fabdcfe3f7dc890f89c0ca2f0ef034d189226531.zip
renderer: added support to truncate variables.
this commit also documents variable formatters properly.
-rw-r--r--man/blogc-source.7.ronn4
-rw-r--r--man/blogc-template.7.ronn36
-rw-r--r--src/renderer.c62
-rw-r--r--tests/check_renderer.c28
4 files changed, 121 insertions, 9 deletions
diff --git a/man/blogc-source.7.ronn b/man/blogc-source.7.ronn
index 9a0c94c..5bb3b32 100644
--- a/man/blogc-source.7.ronn
+++ b/man/blogc-source.7.ronn
@@ -55,7 +55,9 @@ parser. It contains the unparsed content of the first paragraph found in the
source file. The content is not parsed but HTML entities are encoded. Paragraphs
inside blockquotes are ignored. This variable can be overriden by an explicit
definition in source file, that must have the HTML entities escaped manually.
-This is useful to add "description" meta-tags to HTML templates.
+This is useful to add "description" meta-tags to HTML templates. It may be
+needed to truncate the variable size to an maximum length, take a look at
+blogc-template(7).
## SOURCE CONTENT - BLOCK ELEMENTS
diff --git a/man/blogc-template.7.ronn b/man/blogc-template.7.ronn
index bd38618..3499d7c 100644
--- a/man/blogc-template.7.ronn
+++ b/man/blogc-template.7.ronn
@@ -105,6 +105,36 @@ won't raise any error in this case.
Variables are always strings, even if the value of the variable is a number,
it is handled as a string by blogc(1).
+### Variable formatters
+
+blogc(1) can apply a formatter to a variable, depending on how it is called
+in the template. If user append `_FORMATTED` to the end of the variable name,
+a formatter will be applied, if available for the variable name:
+
+- Date formatter: if variable name starts with `DATE_`, it is formatted with
+ a strptime(3) format, provided by `DATE_FORMAT` variable. The `DATE_FORMATTED`
+ "meta-variable" will return the formatted version of the `DATE` variable.
+ If `DATE_FORMAT` is not provided, the original value will be returned.
+
+An existing variable is not overrided by formatter. That means that if
+`FOO_FORMATTED` variable exists, it won't be handled as a formatter
+"meta-variable", and `FOO_FORMATTED` variable value will be returned normally.
+
+### Truncated variables
+
+blogc(1) can truncate the value of a variable to a maximum length, if it is
+called with the maximum length appended to the end of the variable, like:
+`FOO_5` will return the 5 first characters of the `FOO` variable, if bigger
+than 5 characters.
+
+This is applicable to the "meta-variables", like `DATE_FORMATTED`. It can
+be truncated like: `DATE_FORMATTED_5`, that will return the 5 first
+characters of the `DATE_FORMATTED` "meta-variable".
+
+An existing variable is not overrided by the truncate syntax. That means
+that if `FOO_5` variable exists, it won't be handled as a truncate
+"meta-variable", and `FOO_5` variable value will be returned normally.
+
## TEMPLATE CONDITIONALS
Template conditionals are used to include content to the output, or not,
@@ -199,6 +229,12 @@ iteration.
If the value of the `TAGS` variable is "item1 item2 item3", this template is
rendered 3 times, one for each item value.
+The `FOREACH_ITEM` variable can be truncated, like:
+
+ {% foreach TAGS %}
+ <a href="/tag/{{ FOREACH_ITEM }}/">{{ FOREACH_ITEM_5 }}</a>
+ {% endforeach %}
+
## WHITESPACE CONTROL
Users can control how whitespaces (space, form-feed (`\f`), newline (`\n`),
diff --git a/src/renderer.c b/src/renderer.c
index 5af3b8a..0f71ba7 100644
--- a/src/renderer.c
+++ b/src/renderer.c
@@ -10,6 +10,7 @@
#include <config.h>
#endif /* HAVE_CONFIG_H */
+#include <errno.h>
#include <stdbool.h>
#include <stdio.h>
#include <string.h>
@@ -61,6 +62,12 @@ char*
blogc_format_variable(const char *name, sb_trie_t *global, sb_trie_t *local,
sb_slist_t *foreach_var)
{
+ // if used asked for a variable that exists, just return it right away
+ const char *value = blogc_get_variable(name, global, local);
+ if (value != NULL)
+ return sb_strdup(value);
+
+ // do the same for special variable 'FOREACH_ITEM'
if (0 == strcmp(name, "FOREACH_ITEM")) {
if (foreach_var != NULL && foreach_var->data != NULL) {
return sb_strdup(foreach_var->data);
@@ -68,30 +75,69 @@ blogc_format_variable(const char *name, sb_trie_t *global, sb_trie_t *local,
return NULL;
}
- char *var = NULL;
+ char *var = sb_strdup(name);
+
+ size_t i;
+ size_t last = strlen(var);
+
+ long int len = -1;
+
+ // just walk till the last '_'
+ for (i = last - 1; i > 0 && var[i] >= '0' && var[i] <= '9'; i--);
+
+ if (var[i] == '_' && (i + 1) < last) { // var ends with '_[0-9]+'
+ // passing NULL to endptr because our string was previously validated
+ len = strtol(var + i + 1, NULL, 10);
+ if (errno != 0) {
+ fprintf(stderr, "warning: invalid variable size for '%s' (%s), "
+ "ignoring.\n", var, strerror(errno));
+ len = -1;
+ }
+ else {
+ var[i] = '\0';
+ }
+ }
+
bool must_format = false;
- if (sb_str_ends_with(name, "_FORMATTED")) {
- var = sb_strndup(name, strlen(name) - 10);
+
+ if (sb_str_ends_with(var, "_FORMATTED")) {
+ var[strlen(var) - 10] = '\0';
must_format = true;
}
- if (var == NULL)
- var = sb_strdup(name);
- const char *value = blogc_get_variable(var, global, local);
+ if ((0 == strcmp(var, "FOREACH_ITEM")) &&
+ (foreach_var != NULL && foreach_var->data != NULL))
+ value = foreach_var->data;
+ else
+ value = blogc_get_variable(var, global, local);
+
free(var);
if (value == NULL)
return NULL;
char *rv = NULL;
+
if (must_format) {
if (sb_str_starts_with(name, "DATE_")) {
rv = blogc_format_date(value, global, local);
}
+ else {
+ fprintf(stderr, "warning: no formatter found for '%s', "
+ "ignoring.\n", var);
+ rv = sb_strdup(value);
+ }
+ }
+ else {
+ rv = sb_strdup(value);
+ }
+
+ if (len > 0) {
+ char *tmp = sb_strndup(rv, len);
+ free(rv);
+ rv = tmp;
}
- if (rv == NULL)
- return sb_strdup(value);
return rv;
}
diff --git a/tests/check_renderer.c b/tests/check_renderer.c
index 13e7309..0f17d23 100644
--- a/tests/check_renderer.c
+++ b/tests/check_renderer.c
@@ -820,18 +820,30 @@ test_format_date_without_date(void **state)
static void
test_format_variable(void **state)
{
+ // FIXME: test warnings
sb_trie_t *g = sb_trie_new(free);
sb_trie_insert(g, "NAME", sb_strdup("bola"));
sb_trie_insert(g, "TITLE", sb_strdup("bola2"));
sb_trie_t *l = sb_trie_new(free);
sb_trie_insert(l, "NAME", sb_strdup("chunda"));
sb_trie_insert(l, "TITLE", sb_strdup("chunda2"));
+ sb_trie_insert(l, "SIZE", sb_strdup("1234567890987654321"));
char *tmp = blogc_format_variable("NAME", g, l, NULL);
assert_string_equal(tmp, "chunda");
free(tmp);
tmp = blogc_format_variable("TITLE", g, l, NULL);
assert_string_equal(tmp, "chunda2");
free(tmp);
+ tmp = blogc_format_variable("TITLE_2", g, l, NULL);
+ assert_string_equal(tmp, "ch");
+ free(tmp);
+ tmp = blogc_format_variable("SIZE_12", g, l, NULL);
+ assert_string_equal(tmp, "123456789098");
+ free(tmp);
+ tmp = blogc_format_variable("SIZE_200", g, l, NULL);
+ assert_string_equal(tmp, "1234567890987654321");
+ free(tmp);
+ assert_null(blogc_format_variable("SIZE_", g, l, NULL));
assert_null(blogc_format_variable("BOLA", g, l, NULL));
sb_trie_free(g);
sb_trie_free(l);
@@ -849,6 +861,12 @@ test_format_variable_with_date(void **state)
char *tmp = blogc_format_variable("DATE_FORMATTED", g, l, NULL);
assert_string_equal(tmp, "14:15");
free(tmp);
+ tmp = blogc_format_variable("DATE_FORMATTED_3", g, l, NULL);
+ assert_string_equal(tmp, "14:");
+ free(tmp);
+ tmp = blogc_format_variable("DATE_FORMATTED_10", g, l, NULL);
+ assert_string_equal(tmp, "14:15");
+ free(tmp);
sb_trie_free(g);
sb_trie_free(l);
}
@@ -860,9 +878,18 @@ test_format_variable_foreach(void **state)
sb_slist_t *l = NULL;
l = sb_slist_append(l, sb_strdup("asd"));
l = sb_slist_append(l, sb_strdup("qwe"));
+ l = sb_slist_append(l, sb_strdup("zxcvbn"));
char *tmp = blogc_format_variable("FOREACH_ITEM", NULL, NULL, l->next);
assert_string_equal(tmp, "qwe");
free(tmp);
+ tmp = blogc_format_variable("FOREACH_ITEM_4", NULL, NULL,
+ l->next->next);
+ assert_string_equal(tmp, "zxcv");
+ free(tmp);
+ tmp = blogc_format_variable("FOREACH_ITEM_10", NULL, NULL,
+ l->next->next);
+ assert_string_equal(tmp, "zxcvbn");
+ free(tmp);
sb_slist_free_full(l, free);
}
@@ -871,6 +898,7 @@ static void
test_format_variable_foreach_empty(void **state)
{
assert_null(blogc_format_variable("FOREACH_ITEM", NULL, NULL, NULL));
+ assert_null(blogc_format_variable("FOREACH_ITEM_4", NULL, NULL, NULL));
}