Snippetory
how to craft your texts
According to wikipedia a template engine "...". This is not exactly what Snippetory does. As well the term 'engine' refers to providing activity to the templates. This is not true for Snippetory as well, as it features passive templates. This is why I prefer the term templating platform. However, the point of this little introduction is: Snippetory is different from what most people know in templating. It rather models a paper form, where data is filled in by 'someone' else. Of course this form can have repetitive, optional and alternative parts. However, the communication always happens on a pretty fine-grained level. This is a pattern many templating facilities are build on. In consequence, to replace a script based template one needs a passive template and 'someone', the renderer.
As obvious from that model it makes great sense to build the template first, before the renderer is built. However, before jumping into the template we need to define the task.
A calendar page
I think a presentation of single month is a nice little example, and we can even get localisation for free. Now let's jump into it. As always with Snippetory I start with a template. This is obviously a good choice, as to fill data into the form one needs a form.
Now, how should it look like? We have a heading consisting of month and year. The days are presented in a grid, where any cell has large number to express the day of month and the smaller name of the day of week. And one row per week.
<table >
<caption>{v:month date="MMMM yyyy"}</caption>
<tr>
<t:caption>
<th>{v:week-day date="EEEE"}</th>
</t:caption>
</tr>
<t:week>
<tr>
{v:target}
<t:day-in>
<td style="text-align:right;">{v:day date="d"}</td>
</t:day-in>
<t:day-out>
<td style="color:grey; text-align:right;">{v:day date="d"}</td>
</t:day-out>
</tr>
</t:week>
</table>
public class Calendar {
private final TemporalField weekField;
private final Template calendar;
public Calendar(Locale l) {
this.weekField = WeekFields.of(l).dayOfWeek();
this.calendar = Repo.readResource("calendar.html").encoding(Encodings.html).locale(l).parse();
}
public Template render(YearMonth month) {
LocalDate dayCounter = month.atDay(1).with(weekField, 1);
LocalDate end = month.atEndOfMonth().with(weekField, 7).plusDays(1);
calendar.set("month", month);
for (long i = 1; i <= 7; i++) {
calendar.get("caption").set("week-day", dayCounter.with(weekField, i)).render();
}
while (dayCounter.isBefore(end)) {
Template weekTpl = calendar.get("week");
for (int i = 1; i <= 7; i++) {
String tpl = YearMonth.from(dayCounter).equals(month) ? "day-in" : "day-out";
weekTpl.get(tpl).set("day", dayCounter.atStartOfDay()).render("target");
dayCounter = dayCounter.plusDays(1);
}
weekTpl.render();
}
return calendar;
}
}