Make cl-template able to trim spaces

The contents of this site are written in gemtext[1] markup language and then published as both a Gemini capsule and a web site. I wrote a generator program in Common Lisp to build the capsule from a bunch of gemtext files, so I need a template library which works for output not only in HTML. I found cl-template[2] which is just such a library I need, as said in its document:

It can be used for any output. Most Common Lisp template engines devise some mapping from s-expressions to HTML. cl-template can generate HTML, JSON, CSV, Markdown, or any other text-based format.

It's just Lisp. The only other output-agnostic template engines that I found, CL-EMB and the somewhat misnamed HTML-TEMPLATE have additional syntax. In the case of HTML-TEMPLATE it doesn't use Lisp at all, only special template directives. CL-EMB mostly uses Lisp, but has special directives like @if and @loop.

I like these design approaches. However, due to the lack of ability to handle unwanted spaces generated by the template, It's quite inconvenient to use for output formats which are space sensitive. Gemtext is spaces sensitive - blank lines are rendered verbatim by clients verbatim. For example, given the template:

Index page:

<% if (@ page) %>
<%= page-body (@ page) %>
<% end %>

<% loop for post in (@ children) do %>
=> /<%= page-url post %> <%= page-date post %> - <%= page-title post %>
<% end %>

Some other text.

Apply it produces something like:

Index page:


# Page content title
Page content line1



=>/post-2-2023-12-06.gmi 2023-12-06 - Post 2

=>/post-1-2023-12-05.gmi 2023-12-05 - Post 1


Some other text.

You can see a lot of unwanted blank lines. It's because all text between actions are copied verbatim when template is executed, as '(write-string text stream)' expressions. So every newline after the end delimiter ("%>") are included as is.

Go's text/template library takes care of this problem by providing options for user to trim out the leading and preceding spaces. You can find the details in "Text and Spaces"[3] section on its document. So I added a similar feature to cl-template:

More details can be found in the Readme.org[4] of the modified version cl-template-trim. It's currently not on Quicklisp, as I think it's better to be merged into its upstream cl-template ultimately.

Now with the trim options on:

Index page:

<% if (@ page) -%>
<%= page-body (@ page) -%>
<% end -%>

<% loop for post in (@ children) do -%>
=> /<%= page-url post %> <%= page-date post %> - <%= page-title post %>
<% end -%>

Some other text

The output is much more as expected:

Index page:

# Page content title
Page content line1

=>/post-2-2023-12-06.gmi 2023-12-06 - Post 2
=>/post-1-2023-12-05.gmi 2023-12-05 - Post 1

Some other text.

Implementation

The implementation is straightforward:

There is also a few fixes on tests and system definition to stop the complains from recent version ASDF.

--------

[1]gemtext

[2]cl-template

[3]Text and Spaces

[4] cl-template-trim

---------------------

Published on 2023-12-07

The content for this site is licensed under:

CC-BY-SA