All Projects → tkrajina → ftmpl

tkrajina / ftmpl

Licence: Apache-2.0 license
Fast typesafe templating for golang

Programming Languages

go
31211 projects - #10 most used programming language
Makefile
30231 projects
shell
77523 projects

Projects that are alternatives of or similar to ftmpl

jquery-smarty
jQuery Smarty Plugin (jQSmarty) is a port of the Smarty Templating Engine to Javascript/jQuery, offering a familiar client-side templating solution
Stars: ✭ 18 (-70.49%)
Mutual labels:  template-engine
babl
JSON templating on steroids
Stars: ✭ 29 (-52.46%)
Mutual labels:  template-engine
opentbs
With OpenTBS you can merge OpenOffice - LibreOffice and Ms Office documents with PHP using the TinyButStrong template engine. Simple use OpenOffice - LibreOffice or Ms Office to edit your templates : DOCX, XLSX, PPTX, ODT, OSD, ODP and other formats. That is the Natural Template philosophy.
Stars: ✭ 48 (-21.31%)
Mutual labels:  template-engine
nornj
More exciting JS/JSX based on Template Engine, support control flow tags, custom directives, two-way binding, filters and custom operators.
Stars: ✭ 97 (+59.02%)
Mutual labels:  template-engine
esh
Simple templating engine based on shell.
Stars: ✭ 165 (+170.49%)
Mutual labels:  template-engine
gender-render
Template-system and proof-of-concept for rendering gender-neutral text-, email- and RPG-text-templates with the correct pronouns of all people involved.
Stars: ✭ 21 (-65.57%)
Mutual labels:  template-engine
escapevelocity
A subset reimplementation of Apache Velocity with a much simpler API.
Stars: ✭ 28 (-54.1%)
Mutual labels:  template-engine
frep
Generate file using template from environment, arguments, json/yaml/toml config files
Stars: ✭ 135 (+121.31%)
Mutual labels:  template-engine
pypugjs
PugJS syntax adapter for Django, Jinja2 and Mako templates
Stars: ✭ 237 (+288.52%)
Mutual labels:  template-engine
te4j
Fast and easy template engine
Stars: ✭ 20 (-67.21%)
Mutual labels:  template-engine
Context
WordPress package to build a "context" (based on a query object) suiteable to be bassed to templates..
Stars: ✭ 18 (-70.49%)
Mutual labels:  template-engine
modulor-html
Missing template engine for Web Components
Stars: ✭ 36 (-40.98%)
Mutual labels:  template-engine
carbone
Fast and simple report generator, from JSON to pdf, xslx, docx, odt...
Stars: ✭ 810 (+1227.87%)
Mutual labels:  template-engine
liquid.cr
Kind of liquid template engine for Crystal [WIP]
Stars: ✭ 64 (+4.92%)
Mutual labels:  template-engine
morestachio
Lightweight, powerful, flavorful, template engine.
Stars: ✭ 45 (-26.23%)
Mutual labels:  template-engine
ultron-ele
The world’s fastest LMS engine based on Gatsby -- Deliver knowledge with fun!
Stars: ✭ 27 (-55.74%)
Mutual labels:  template-engine
Fuga-Framework
Web Framework for Java
Stars: ✭ 15 (-75.41%)
Mutual labels:  template-engine
dry
Dry is a new template engine and language, and is a superset of Shopify's Liquid, with first-class support for advanced inheritance features, and more. From the creators of Enquirer, Assemble, Remarkable, and Micromatch.
Stars: ✭ 66 (+8.2%)
Mutual labels:  template-engine
tenjin
📝 A template engine.
Stars: ✭ 15 (-75.41%)
Mutual labels:  template-engine
templatel
Jinja inspired template language for Emacs Lisp
Stars: ✭ 46 (-24.59%)
Mutual labels:  template-engine

Build Status

FTMPL: fast (and typesafe) templating for Golang

ftmpl is a fast/compiled/typesafe templating "language" for golang.

Why ftmpl?

  • It's faster (run go test -v . -run=TestComparisonWithGolangTemplates for a comparison). The builtin templates involve a lot of reflection, ftmpl "compiles" to simple Golang functions.
  • No need to learn another templating "language", ftmpl is just plain Go
  • Type safety (why have a typesafe language and a nontypesafe templating engine?)
  • Base/extended templates

Installation

go get github.com/tkrajina/ftmpl

Templating files and functions

Every template must be saved in a file with extension .tmpl. The template file can be "compiled" in Go code (and this is typically done in the build procedure).

If the file is named MyTemplate.tmpl then the ftmpl utility will produce a function TMPLMyTemplate().

Compiling files is done my invoking:

ftmpl -targetgo target_dir/templates_generated.go source_dir

The resulting code is pretty straightforward, and you will probably need to check (but not edit!) it in case of errors.

For template examples see here (.tmpl files). For the "compiled" golang code from those examples see here. The resulting code is always formatted using go fmt.

If you prefer using go generate add a comment...

//go:generate ftmpl -targetgo target_dir/templates_generated.go source_dir

...anywhere in your code.

The prefix TMPL in the function name can be changed by a cmd line switch.

Watch and recompile

ftmpl can "watch" for changes in your source directory. When any of the *.tmpl files change there, it will "recompile" all the templates. Just add -watch when calling it:

ftmpl -watch -targetgo target_dir/templates_generated.go source_dir

If you start multiple ftmpl "watch" processes, you can stop them all with:

ftmpl -unwatchall

Template files

An example template ShowTime.tmpl

!#import "time"
<html>
    <body>
        It's {{s time.Now().String() }}
    </body>
</html>

It will be compiled to the function func TMPLShowTime()

Templates with arguments

If you want your template function to have arguments:

!#import "time"
!#arg t time.Time
<html>
    <body>
        It's {{s t.String() }}
    </body>
</html>

Now the compiled function will be func TMPLShowTime(time.Time)

Placeholders

Placeholders are expressions to be executed and written when calling the template. Since ftmpl is a typesafe templating it needs to know of which type is the expression, and based on that to properly format it:

Use:

  • {{s expression }} for string expressions
  • {{d expression }} for number expressions
  • {{t expression }} for bool expressions
  • ...

It's simple, when compiled {{s expression }} will end up as fmt.Sprintf("%s", expression), {{v expression }} as fmt.Sprintf("%v", expression), etc.

{{ expression }} is the same as {{v expression }}.

For more complex formatting, prefix with %:

  • {{%5.5f 1.222222222 }} is equivalent to fmt.Sprintf("%5.5f", 1.222222222)
  • {{% 15f "padded" }} is equivalent to fmt.Sprintf("% 15f", "padded")

Escape and unsecape

If you use {{s expresssion }} the result will be escaped using html.EscapeString(). If you want to write the exact same string (without escaping), use {{=s expression }}.

Important {{v expression }} is not escaped even when the resulting expression is a string!

Code

There are two ways to write go code in templates:

Lines starting with "!"

!#arg n int
<html>
    <body>
!for i := 0; i < n; i++ {
        i is now {{d i }}
!}
    </body>
</html>

Basically every line starting with ! (but not !#) will be translated as go code in the resulting function.

If you (really?) need a non-golang line starting with ! start it with !!.

Embedded code

!#arg n int
<html>
    <body>
        {{! for i := 0; i < n; i++ { }}i is now {{d i }}{{! } }}
    </body>
</html>

...so by using {{! code }} you embed a go command in that place.

Note that (unlike some other templating languages) the {{! code }} notation is not multiline. It must contain only one go command/line.

For for and if control structures you can ommit {, } or } else { (open and close block of code). Use end to close and else (with if) instead:

For example if:

{{! if n > 0 }}{{d n}} biger than 0{{! end }}
{{! if n > 5 }}{{d n}} biger than 5{{! else }}{{d n}} smaller than 5{{! end }}

With for...

{{! for i := 0; i < n; i++ }} i={{d i }} {{! end }}

...or as ! lines:

!for i:=0; i < 5; i++
    i is now {{d i }}
!end

Directives

Like Go code, special "directive" commands like !#arg or !#import can also be used as lines starting with !# or embedded in the code: {{!#import "time" }}, {{!#return }}, ...

Exit from template

To prematurely end the execution with an error (depending on an expression), you can use:

!#errif <expression>, "<error_message>"

...or...

!#return

Base templates and extensions

When you need a base website template, and pages "extending it":

!#arg title string
<html>
    <head>
        <title>{{s title }}</title>
!#include head
    </head>
    <body>
!#include body
!#include footer
    </body>
</html>

And then a typical page will be something like:

!#extends base
!#arg something int

!#sub head
<script>
alert("included")
</script>

!#sub body
<h1>Body!</h1>

If the name of the extended template is MyPage.tmpl then the resulting template function will have both the arguments from that template and arguments from the base template: func TMPLMyPage(title string, something int).

Typically you will have many template arguments, so the best way to deal with them is to pack them all into one "base page structure" and another struct for every page. The function will then be func TMPLMyPage(baseParams BasePageParams, pageParams MyPageParams)

If a !#sub chunk is declared in the extended template, but not in the base -- ftmpl will show you a warning during compilation.

Inserting (sub)templates

Sometimes you need some templates just "copied" in other templates. You can do that with !#insert. For example:

!#arg a int
Will insert something here: {{!#insert "insertion.tmpl" }}

The insertion.tmpl template file:

!#nocompile
a={{d a }}

Is equivalent to:

!#arg a int
Will insert something here: a={{d a }}

Note that the insertion.tmpl alone is an invalid template because it contains a previously undeclared variable a. But, when inserted, then the variable a is OK. That template makes sense only when included in another template. That's why it has !#nocompile in it.

Another way to do inserts is to just call the generated template function:

!#arg a int
Will insert something here: {{=s TMPLinsertion(a) }}

In this case insertion.tmpl must not have !#nocompile, and the variable a must be declared with !#arg a int.

No compile

Some template files make no sense alone. For example, templates used only in !#insert directives or base templates (you never call them alone, but their extended templates).

If you don't want to compile them into golang functions, add the !#nocompile directive.

Invalid code

Some errors in your templates will be reported immediately:

$ ftmpl example/invalid/
invalid.tmpl    -> example/invalid/invalid.go
go fmt example/invalid/invalid.go
Cannot format example/invalid/invalid.go: exit status 1

example/invalid/invalid.go:42:18: unknown escape sequence
       38:    result.WriteString(`    <body>
       39:    `)
       40:    //invalid.tmpl:         {{s "\ " }}
       41:    result.WriteString(fmt.Sprintf(`        %s
-->    42:    `, _escape( "\ ")))
                               ^
       43:    //invalid.tmpl:     </body>
       44:    result.WriteString(`    </body>
       45:    `)
       46:    //invalid.tmpl: </html>
       47:    result.WriteString(`</html>
exit status 2

For others, you'll need to debug the Go code (every Go line is preceded with a Go comment with the original .tmpl file and tmpl code).

Returning errors

Every template will result in two template functions. Both will execute the same code, but:

  • Use func TMPLERRMyTemplate(args) (string, error) if you expect your template to return errors, use this one. Use !return "", err to prematurely exit from the template with a proper error value.
  • With func TMPLMyTemplate(args) string if the template returns an error, the result is an empty string, and the error will be written in os.Syserr.

Global declarations

In case you need a global declaration (outside of the template function), it can be done with !#global:

!#global type Argument struct { Aaa string; Bbb int }
!#arg arg Argument
Aaa is {{s arg.Aaa }}, and Bbb is {{d arg.Bbb }}

The Argument struct will be declared outside the function body, and the function is now TMPLMyTemplate(Argument).

Special variables

_template is defined in the function and contains the current template name.

_ftmpl is a bytes.Buffer which contains the result of the template. _w is an alias to _ftmpl.WriteString. It means that {{! _ftmpl.WriteString("something") }} is equivalent to {{! _w("something") }} which in turn is the same as {{=s "something" }}.

Careful with Go code

Ftmpl allows you to write go code (instead of templating "metalanguages", like other templating engines), but be careful to not write too much of it. Ideally, the data should be prepared before the template function, and the only code in the template would be some basic formatting, a couple of ifs and forloops.

License

ftmpl is licensed under the Apache License, Version 2.0

Note that the project description data, including the texts, logos, images, and/or trademarks, for each open source project belongs to its rightful owner. If you wish to add or remove any projects, please contact us at [email protected].