1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
|
blogc-template(7) -- blogc's template format
============================================
## DESCRIPTION
Template files are used as base to build output files by blogc(1). These files
can include variables, blocks, conditionals and iterators, that will directly
affect the output files.
The syntax of the template files is defined to be simple, without affecting the
content output. The syntax is somewhat inspired by Jinja2 syntax.
Templates must be valid UTF-8.
This manual describes the basic syntax and functionalities of template files.
## TEMPLATE BLOCKS
Template blocks are used to delimit content. The content inside a block will
be included in the output file (or not) if the parameters passed to blogc(1)
matches the requirements of the given block.
Blocks can be defined more than once, but can't be nested.
The available blocks are: `entry`, `listing`, `listing_empty`, `listing_entry`
and `listing_once`.
### entry block
The content of an `entry` block is included in the output file when blogc(1)
is called without `-l` option, and with only one source file. It is used to
render a single entry of your blog/website. All the variables defined in the
source file are available inside this block (see blogc-source(7)), and will
override global variables (see blogc(1)).
This is how an `entry` block is defined:
{% block entry %}
This content will only be included when rendering a single entry.
{% endblock %}
### listing block
The content of a `listing` block is included in the output file when blogc(1)
is called with `-l` option, and with zero or more source files. It is used
to create a listing of entries, and its content will be included once for
each given source file (in the order that the source files were provided to
blogc(1)). All the variables defined in the source files are available
inside this block (see blogc-source(7)), and will override global variables
(see blogc(1)). The variables will be provided by each file, when blogc(1)
iterates over them.
This is how a `listing` block is defined:
{% block listing %}
This content will be only included when rendering an entry listing, and
will be included once for each entry.
{% endblock %}
### listing_empty block
This block is similar to the `listing` block, but its content is included
only when there are no entries to be listed, either because no source files
were provided or because there are no entries remaining after filtering (see
blogc-pagination(7)).
This is how a `listing_empty` block is defined:
{% block listing_empty %}
No entries available.
{% endblock %}
### listing_entry block
This block is identical to the `entry` block, but its content is included in
the output file only when blogc(1) is called with `-l` and `-e` <SOURCE>
options. The variables available in the block are provided by the source
file provided using `-e` <SOURCE> option.
This is how a `listing_entry` block is defined:
{% block listing_entry %}
This content will only be included when rendering a listing, but with
content provided by a single entry.
{% endblock %}
When multiple `listing_entry` blocks are defined, blogc(1) should be called
with multiple `-e` <SOURCE> options. If a `listing_entry` block does not have
a corresponding `-e` <SOURCE> option, or if its value is an empty string,
the content of the `listing_entry` block is not included.
`listing_entry` blocks inside iterator are evaluated as multiple blocks and
also require multiple `-e` <SOURCE> options. blogc(1) won't use the same
source for every iteration.
### listing_once block
The content of a `listing_once` block is included in the output file when
blogc(1) is called with `-l` option, and with zero or more source files. It is
like a `listing` block, but is only called once, and does not have access
to the local variables defined in the source files. It is useful to add
something before an entry listing.
The content of a `listing_once` block is included even if no source file is
provided.
This is how a `listing_once` block is defined:
{% block listing_once %}
This content will be only included when rendering an entry listing, but
will be included only once.
{% endblock %}
This is a 'real world' usage example of a `listing_once` block, supposing
that the `TITLE` variable is defined:
{% block listing_once %}
<ul>
{% endblock %}
{% block listing %}
<li>{{ TITLE }}</li>
{% endblock %}
{% block listing_once %}
</ul>
{% endblock %}
## TEMPLATE VARIABLES
Template variables are used to provide content to templates from blogc(1)
command-line and from source files.
This is how a variable is defined in a template:
{{ VARIABLE_NAME }}
The value of a variable will depends of its scope. Global variables provided
to blogc(1) are available everywhere in the templates. Local variables
provided in the source files are available only inside `entry` and `listing`
blocks, and will override global variables.
If a variable is not defined, it will be replaced by an empty string. blogc(1)
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 strftime(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.
## PREDEFINED TEMPLATE VARIABLES
blogc(1) provides some template variables, that can be used to display some build
metadata in your website.
If some of the variables are not available in the system running the build, they
won't be defined. It is recommended to rely on template conditionals, mainly
`ifdef` and `ifndef` when using these variables.
### Static variables
These variables are always available, and are set during the blogc(1) binary
compilation.
* `BLOGC_VERSION`:
The version of blogc(1) used to build. e.g.: `blogc 0.14.1`.
### Resource usage variables
It is not possible to measure the resource usage of blogc(1) until the end of
the execution, because the rendering of these variables itself is using resources,
and the evaluation of the used resources was already done. To get better values,
it is recommended to use these variables only in the website footer.
* `BLOGC_RUSAGE_CPU_TIME`:
The CPU time used to build, up to the point where this variable was used for
the first time in the template (value is cached). e.g.: `12.345ms`.
* `BLOGC_RUSAGE_MEMORY`:
The memory used to build, up to the point where this variable was used for the
first time in the template (value is cached). e.g.: `1.234MB`.
### System information variables
* `BLOGC_SYSINFO_HOSTNAME`:
The hostname of the machine where the build happened (short hostname only, not
FQDN).
* `BLOGC_SYSINFO_USERNAME`:
The username of the user that executed the build.
* `BLOGC_SYSINFO_DATETIME`:
The GMT datetime of the build. e.g. `2019-02-10 22:00:00`.
* `BLOGC_SYSINFO_INSIDE_DOCKER`:
If built inside a docker container, this variable will be defined, with value `1`.
## TEMPLATE CONDITIONALS
Template conditionals are used to include content to the output, or not,
based on the value and existence of variables in the current scope.
The implementation of conditionals is simple, and each will just evaluate the
value of a single variable.
The available conditionals are: `ifdef`, `ifndef` and `if`. `else` statements
are supported.
### ifdef conditional
The content of an `ifdef` conditional is included in the output file when
the given variable is defined in the current scope.
This is how an `ifdef` conditional is defined in a template:
{% ifdef TITLE %}
This is title: {{ TITLE }}
{% else %}
Untitled entry
{% endif %}
In this case, if the `TITLE` variable is defined, the content after the statement
is included. Otherwise, the content after `else` statement is included.
### ifndef conditional
The content of an `ifndef` conditional is included in the output file when
the given variable is not defined in the current scope.
This is how an `ifndef` conditional is defined in a template:
{% ifndef TITLE %}
Untitled entry
{% endif %}
In this case, if the `TITLE` variable is not defined, the content is included.
`else` statements are supported here, even if it does not makes much sense to
be used this way.
### if conditional
The content of an `if` conditional is included in the output file when
the comparision between the given variable and the given static string or
variable evaluates to true in the current scope. The left operand of the
comparision *must* be a variable.
The available operators are: `==`, `!=`, `<`, `>`, `<=` and `>=`. The
comparisions are strcmp(3)-like.
This is how an `if` conditional is defined in a template:
{% if TITLE == "My Title" %}
Special description of "My Title"
{% else %}
Title is {{ TITLE }}
{% endif %}
Or:
{% if TITLE == DEFAULT_TITLE %}
Title is the default title
{% endif %}
## TEMPLATE ITERATORS
Template iterators are used to iterate over the value of a variable, that is handled
as a list.
The available conditionals are: `foreach`.
### foreach iterator
The content of a `foreach` iterator is included in the output file when the target
variable is defined, and is repeated for each item in the list parsed from the variable
value.
The variable value should be formatted as a space-separated list of items. Quotes are
not supported, as this is intended to work with identifiers, like slugs, and not with
arbitrary strings.
This is how a variable value would be formatted:
item1 item2 item3
For more info about how to define variables, see blogc(1) and blogc-source(7).
This is how a `foreach` iterator is defined in a template:
{% foreach TAGS %}
<a href="/tag/{{ FOREACH_ITEM }}/">{{ FOREACH_ITEM }}</a>
{% endforeach %}
Where `TAGS` is the variable with space-separated list of items, and `FOREACH_ITEM`
is the variable defined by blogc(1), that will store the item for a given iteration.
If the value of the `TAGS` variable is "item1 item2 item3", this template is
rendered 3 times, one for each item.
It is possible to map the items to arbitrary strings by defining other variables
following a predefined for naming schema, like:
TAGS__ITEM1
Where `TAGS` is the variable defined in the foreach iterator, and `ITEM1` is the
current iteration item (the value of `FOREACH_ITEM` for the current iteration,
converted to upper case and with special characters converted to `_`).
This is how a `foreach` iterator using arbitrary string mapping is defined in a template:
{% foreach TAGS %}
<a href="/tag/{{ FOREACH_ITEM }}/">{{ FOREACH_VALUE }}</a>
{% endforeach %}
`FOREACH_VALUE` is the variable defined by blogc(1), that will store the arbitrary string
mapped to current iteration item. This variable can be checked using `ifdef` conditionals
(and similar) as usual:
{% foreach TAGS %}
{% ifdef FOREACH_VALUE %}
<a href="/tag/{{ FOREACH_ITEM }}/">{{ FOREACH_VALUE }}</a>
{% endif %}
{% endforeach %}
The `FOREACH_ITEM` and `FOREACH_VALUE` variables can be truncated, like:
{% foreach TAGS %}
<a href="/tag/{{ FOREACH_ITEM_5 }}/">{{ FOREACH_VALUE_5 }}</a>
{% endforeach %}
## WHITESPACE CONTROL
Users can control how whitespaces (space, form-feed (`\f`), newline (`\n`),
carriage return (`\r`), horizontal tab (`\t`), and vertical tab (`\v`)) are
handled before and after statements delimited with `{%` and `%}` sequences,
respectively.
Adding a minus sign (`-`) after a `{%` sequence (`{%-`) will remove whitespaces
before the sequence and after the last non-whitespace character before the sequence.
Adding a minus sign (`-`) before a `%}` sequence (`-%}`) will remove whitespaces
after the sequence and before the first non-whitespace character after the sequence.
## BUGS
The template content is handled by handwritten parsers, that even being well
tested, may be subject of parsing bugs. Please report any issues to:
<https://github.com/blogc/blogc>
## AUTHOR
Rafael G. Martins <<rafael@rafaelmartins.eng.br>>
## SEE ALSO
blogc(1), blogc-source(7), strcmp(3), strftime(3)
|