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 grammar. You should feel familiar with Sketch if you are familiar with Python.
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>
The contents between <%
and %>
look quite similar to the Python
syntax. Actually, 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) any Python syntax in your sketches but with some modifications:
- All the python style syntax is wrapped between
<%
and%>
. - Indent 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 of sketches 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
have ambiguity of 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 simplest and the most common-used(perhaps) statement in the whole Templating System.
=
is the statement keyword, and the expression following the keyword
will be evaluated by the interpreter. You can also await
an
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 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
establish an new indentation until another unindent statement or
half-indent statement is reached.
Warning
Redundant 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 time stamps until a positive value is selected by random function.
Note
The keywords of inline statements are break
, continue
,
import
, from
, raise
, assert
,
nonlocal
, and global
.
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.
Include¶
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
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
being drawn, it will ask the sketch finder to find
layout.html
and update all the blocks in layout.html
with the blocks in
main.html
. The other content outside the blocks in main.html
can be
accessed using self.body
in layout.html
.
Hint
If the 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 the comment. %>
When the sketch is being drawn, the comment will be excluded.
The result of the example above is:
This is the content.