The Sketch Templating Language¶
The sketch templating language is aiming to generate flexible output for arbitrary text file. It is designed for Pythonistas with statement marks inspired by ERB and a Python like syntax.
Example¶
<!DOCTYPE>
<html>
<head>
<title><%= await handler.get_page_title() %></title>
</head>
<body>
<main>
<% async for item in handler.db.items.find() %>
<article>
<div class="title"><%= item["title"] %></div>
<div class="author"><%= item["author"] %></div>
<div class="content"><%= item["content"] %></div>
</article>
<% end %>
</main>
</body>
</html>
Contents between <%
and %>
may look quite similar to Python
syntax. As a matter of fact, Sketchbook rewrites sketches into Python code and
asks the Python interpreter to “compile” the plain Python code into Python byte
code.
Hence, You can use (almost) all Python syntax in your sketches but with some modifications:
All python style syntax is wrapped between
<%
and%>
.Indentation is not indicated by
:
any more, but controlled by a special<% end %>
statement.
Also, print()
function still prints to sys.stdout
by default.
To print to the template, use SketchRuntime.write()
or output
statements.
Statement Mark¶
All the statements are wrapped under statement marks -
<%
and %>
.
Statement Mark Escape¶
<%%
and %%>
escape <%
and %>
respectively.
e.g.: The following sketch:
<%% is the begin mark, and <%r= "%%> is the end mark. " %>
<%r= "<% and" %> %> only need to be escaped whenever they
are ambiguous to the templating system.
will be drawn like:
<% is the begin mark, and %> is the end mark.
<% and %> only need to be escaped whenever they
have ambiguity of the templating system.
Output¶
The most commonly-used(perhaps) statement in the Templating System.
=
is the statement keyword, and the expression following the keyword
will be evaluated by the interpreter. You can also await
a
collections.abc.Awaitable
:
Hello, <%= await user.get_user_name() %>.
The result will be passed to SketchRuntime.write()
and escaped by the
default
escape function.
Raw Output¶
To output raw strings without escaping, use raw=
(or r=
for
shorthand) as a keyword. In this case, raw
is the escape function for
statement instead of default
.
For how to override the default escape function, define
custom escape functions and view built-in escape functions, please see the
documentation for BaseSketchContext
.
Indentation¶
Indentation is used to control the flow on how the sketch is drawn. There’re three types of keywords to control the indentation:
Indent keywords:
if
,with
,for
,while
,try
andasync
.Unident keyword:
end
.Half-indent keywords:
else
,elif
,except
andfinally
.
Indent keywords is used to start an indentation, and the unindent keyword is used to finish the indentation created by the last indent keyword.
Half Indentation¶
Half-indent keywords is a special type. It unindents the last indentation, and establishes a new indentation at the same time.
Example:
<% if a == b %>
<%= "They are the same." %>
<% else %>
<%= "They are not the same." %>
<% end %>
The if
statement creates an indenation as discussed above, and the
else
statement will automatically unident the if
statement, and
create a new indentation until another unindent statement or
half-indent statement is reached.
Warning
Redundant or missing unindent statements will raise a SketchSyntaxError
.
Inline¶
The statement represents a Python inline keyword.
Example:
<% from time import time as get_timestamp %>
<% import random %>
<% while True %>
<%r= str(get_timestamp()) %>
<% if random.choice(range(0, 2)) %>
<% break %>
<% end %>
<% end %>
This example will output timestamps until a positive value is selected by
random.random()
.
Note
Keywords of inline statements are break
, continue
,
import
, from
, raise
, assert
,
nonlocal
, and global
.
Variable Assignment¶
In Python language, keyword =
is used to assign values to variables.
However, in order to set a variable in sketches, you have to use an additional
keyword let
:
<% try %>
<%= a %>
<% except NameError %>
Variable a is not set.
<% end %>
<% let a = "whatever" %>
Variable a is set to <%= a %>.
This should output
Variable a is not set.
Variable a is set to whatever.
Inclusion¶
Include another sketch into the current sketch.
Example:
header.html
:
<header>
<h1>Site Title</h1>
</header>
main.html
:
<html>
<head>
<title>Main Page</title>
</head>
<body>
<% include "header.html" %>
<main>
<p>Thank you for visiting.</p>
</main>
</body>
</html>
When main.html
is being drawn, it will ask the finder to find
header.html
and draw header.html
at the runtime,
then append it to the result of main.html
.
The result of the example above is:
<html>
<head>
<title>Main Page</title>
</head>
<body>
<header>
<h1>Site Title</h1>
</header>
<main>
<p>Thank you for visiting.</p>
</main>
</body>
</html>
Inheritance¶
Inherit from other sketches. When a sketch with an inherit
statement is
being drawn, a subclass of BaseSketchFinder
will find the parent sketch.
The parent sketch will then being drawn with .SketchRuntime.body
set to the output
of the original sketch. The blocks of the parent sketch will be replaced with the
ones in the child sketch.
Example:
layout.html
:
<html>
<head>
<title><% block title %><% end %></title>
<% block head %><% end %>
</head>
<body>
<%r= self.body %>
</body>
</html>
main.html
:
<% inherit "layout.html" %>
<% block title %>Main Page<% end %>
<main>
<p>Thank you for visiting.</p>
</main>
When main.html
is being drawn, it will ask the sketch finder to find
layout.html
and update all the blocks in layout.html
with blocks in
main.html
. Other content outside blocks in main.html
can be
accessed using self.body
in layout.html
.
Hint
If Inheritance is not enabled, the block
statement has no effect.
Important
When drawing the self.body
, make sure to use Raw Output,
or the it may be escaped.
Warning
If the sketch being drawn is not a parent of another sketch, using self.body
will raise an SketchDrawingError
.
The result of the example above is:
<html>
<head>
<title>Main Page</title>
</head>
<body>
<main>
<p>Thank you for visiting.</p>
</main>
</body>
</html>
Comment¶
Strings that will be removed from the result.
This is the content.
<%# This is a comment. %>
When the sketch is being drawn, the comment will be excluded.
The result of the example above is:
This is the content.