This article provides an overview of everything that you, as a template designer, can do with tayra. If you are just starting with tayra for the first time you may want to go through the getting started page first. If you are a developer looking forward to extend tayra language please refer to development page. For more involved features in tayra refer to articles,
You can go through them once you are comfortable with basic features explained here.
The objective of tayra templating is to create concise, beautiful and highly re-usable HTML templates for web. Although it is in the beginning stage, we hope it has succeeded in solving many problems towards that end. Here is a basic list of features and functions available from tayra,
For those who are starting with web-templating,
That is all is required to write your first template.
Template script contain directives and scriptlines, directives must come in the beginning of the document, followed by template script. Template scripts are made up of tags, statements, comments, textlines, functions, control-blocks like if-elif-else, for while and filter-blocks.
Expression-substitution can be applied pretty much anywhere in the document with few exceptions like, inside comments and control statements.
Tag definitions can be abstracted into functions with its own local context. Tags that are not part of any function or interface-api will be grouped under the function name body, defined implicitly. It is by making a call to body(), that the final html is generated and returned, the call is automatically done by tayra APIs.
1 2 3 4 5 6 7 8 9 10 11 12 13 | @doctype html
<html lang="en">
<head>
<title> My Webpage
<body>
<ul #navigation>
@for item in navigation :
<li> <a "${ item.href }"> ${ item.caption }
<h1> My Webpage
${ a_variable }
|
Shotcuts are tokens for tag attributes. Like the example above some attributes are common to all tags, like, id (tokens prefixed with #) and class (tokens separated by .) shortcuts have common syntax for all tags. While other tokens can be specific to individual tags. Plugins implementing tayra.interfaces.ITayraTag interface is responsible for translating shortcuts to corresponding tag-attributes. Following is a list of common shortcuts,
Here is an example,
1 2 3 4 | <!-- File name : eg2.ttl -->
<p #welcome .intro.highlight> hello world
<a :anchor-name "http://gnu.org" {color : red}> gnu is not unix
|
Other than shortcuts, regular html attribute syntax is also supported inside the tag.
Expression substitution is, more or less, allowed anywhere inside the template script. While translating to HTML output, templates can insert dynamic content using expression substitution. Expressions are enclosed within ${ ... }, where text within curly braces are interpreted as python expression. Expression will be evaluated, converted to string, piped through filters (if supplied) and the result is substituted in the final html. Any valid python expression is equally valid here. Other than expressions, a full python statement, in a single line, can be used in the template by prefixing them with @@. Let us see an example for this,
Escape filtering
Like mentioned before final value emitted by the python expression will be converted to string before substituting them in HTML output. But before substituting the string, it is possible to apply one or more filters on the output string. Filters are applied in the specified order.
1 2 3 4 5 6 7 8 9 | <!-- File name : eg3.ttl -->
@@ content = "hello world, %s times"
@@ rawhtml = "HTML snippet, <pre> hello world </pre>"
@@ html = "Install couchdb <pre> sudo apt-get install couchdb </pre>"
<div>
${ content % 5 }
${ rawhtml | h }
${ html | n }
|
Above example defines 3 variables content, rawhtml, html and substitutes their value inside the div element. It is also possible to substitute variables that come from web application context. Note that assignments in python are statements, so they are not allowed inside expression-substitution syntax.
The above example when translted to html, will look like,
1 2 3 4 5 | <div >
hello world, 5 times
HTML snippet, <pre> hello world </pre>
Install couchdb using command <pre> sudo apt-get install couchdb </pre>
</div>
|
Expressions are handled by plugins. Available list of expression plugins expressions and filtering.
Comments can be of two forms,
1 2 3 4 5 6 7 8 9 10 11 12 | <!--
This file is subject to the terms and conditions defined in
file 'LICENSE', which is part of this source code package.
Copyright (c) .... ..................
-->
@def func( name ) :
## This comment will be silently ignored.
<div {} >
<a #${'idname'} .${'cls'} "http://pluggdapps.com"> hello ${name}
${ func( 'napster' ) }
|
In the above example the copyright notice will be preserved in the final HTML output while developer comments starting with ## will be ignored.
Control blocks allow to selectively include parts of template script based on predicates. Other control blocks like for and while can be used to repeat a block of template script based on predicates. While a python statements can be included inside the template script by prefixing them with @@ token, control blocks are prefixed with @, and the block of template script under the control block must be indented to the right. Let us see an example now,
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 | @if bodylocal == 'pass' :
@@pass
@elif bodylocal == 2 :
The program, designed by Odyssey Space Research, will allow crew members
to conduct several experiments with the phones' cameras, gyroscopes and
other
@else :
<abbr "World Health Organization"> WHO
<button #id_ reset disabled makefriend "button value">
<table>
@for i in range(100) :
<tr>
@@j = 0
@while j < 4 :
<td> sample text
@@j += 1
|
Above example demonstrates the use of control blocks. It uses a variable called bodylocal availabe in template’s context to selectively pick script blocks based on a predicate.
Finally, a table of 100 rows and 4 columns is generated using an outer variable i and an inner variable j, which gets updated on every iteration of the outer loop.
loop controls
It is possible to use break and continue in loops. When break is reached, the loop is terminated; if continue is reached, the processing is stopped and continues with the next iteration. The following is an example,
1 2 3 4 5 6 7 8 9 10 11 12 | @for user in users :
@if user.startswith('admin-') :
@@continue
...
## Likewise a loop that stops processing after the 10th iteration:
@@i = 0
@while users :
@if i >= 10 :
@@break
...
|
Template functions are ways to abstract and reuse template script. Although the syntax and signature of a template-function follows python rules, they do not abstract python code, instead they abstract template script intended to right by two spaces from function signature.
Functions can be called, with positional arguments and key-word arguments, and return html text, which shall be substituted in the caller’s context using exrpression-substitution.
Functions are always called inside expression substitution syntax ${ ... }. Functions also provide a local context for template blocks that are encapsulated under it. Functions can be nested and follows the same scoping rules defined by python functions. A function’s definition starts with a newline followed by one or more white-space and continues with the function signature.
Function signature starts with @def keyword and ends with a colon (:).
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 | @def justtext() :
Google will join its biggest mobile rival, Apple, on the space trip as
well. Apple's iPhone 4 will join a crew running an app, called
"SpaceLab for iOS."
@def involved( z ):
<abbr "World Health Organization"> ${z}
@def nestedfunc() :
<b> this is nested function
@def nestednestedfunc() :
<em> this is nested nested function
${ nestednestedfunc() }
<button #id_ reset disabled makefriend "button value">
${ nestedfunc() }
${ justtext() }
${ involved( 'WHO' ) }
|
When functions are combined with template modules, it will provide a powerful way to abstract and organise your view-templates.
Directives are meta commands specified right at the top of the template script. Here is a shotlist of directives defined by tayra,
For detailed explanations refer to template directives.
Developers can abstract and organise their templates as a library or a tool-kit. Since every template script is compiled and interpreted as a python module, importing them is similar to importing a python module using @include directive.
The import directive specifies which template file to be imported and the name to access the template module. For example,
1 2 3 4 5 | @include etsite:templates/_base/elements.ttl as e
@import os, sys
@def body_leftpane() :
${e.leftpane( menupane )}
|
Here elements.ttl is imported as a template module e, which can be referred in the template script. Further down, you can notice that library function leftpane(...) is called from the imported template module.
Every template script is compiled into a template module and executed as python program to generate the final html output. While loading and executing the template modules it is possible to supply a dictionary of context, like explained in this section. In addition to that some standard set of objects are automatically made available by the runtime engine. One such object is h helper container object that supplies wide variety of library functions that can be useful while scripting your templates.
Tayra follows configurations and settings provided by pluggdapps component architecture. Tayra compiler is implemented as a pluggdapps plugin and hence can be configured like configuring any other plugin under pluggdapps platform.