template

package module
v1.2.2 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Mar 11, 2019 License: GPL-3.0 Imports: 11 Imported by: 0

README

Go template toolkit

Build Status

Description

The ttgen generates Go code from a template description. The template syntax looks like Perl Template-Toolkit (http://template-toolkit.org/), but not the same because Go is compiled language.

Performance

It's faster than native Go templates in more than 10 times:

BenchmarkGoCoreTemplate-4           3000           5306959 ns/op         1041697 B/op      31035 allocs/op
BenchmarkQBitTemplate-4            30000            407632 ns/op           36096 B/op       4006 allocs/op

Installation

go get -u github.com/go-qbit/template
go install github.com/go-qbit/template/ttgen

Usage

  1. Write a new wrapper for pages in `template/wrapper.gtt``:

    [% WRAPPER page(caption string) %]
        <!DOCTYPE html>
        <html>
        <head>
            <title>[% caption | html %]</title>
        </head>
        <body>
            [% CONTENT %]
        </<body>
        </html>
    [% END %]
    
  2. Write a new template in `template/index.gtt``:

    [% TEMPLATE Test(header string, users []User) USE WRAPPER page(header) %]
        <h1>[% header | html %]</h1>
        <hr>
        [% FOR user IN users %]
            <p>
                [% PROCESS UserName(user) %]:
                [% user.Age %] ([% IF user.IsMan %]Man[% ELSE %]Woman[% END %])
            </p>
        [% END %]
    [% END %]
    
    [% TEMPLATE UserName(user User) %]
        [% user.Name | html +%] [% user.Lastname | html %]
    [% END %]
    
  3. Define a User type in template/user.go:

    package template
    
    type User struct {
        Name     string
        Lastname string
        Age      uint8
        IsMan    bool
    }
    
  4. Write a main.go file that will process the template:

    //go:generate ttgen template/*.gtt
    package main
    
    import (
        "context"
        "os"
        "template"
    )
    
    func main()  {
         template.ProcessTest(context.Background(), os.Stdout, "<Header>", []template.User{
                {"Ivan", "Sidorov", 20, true},
                {"Petr", "Ivanov", 30, true},
            },
         )
    }
    
  5. Generate Go code: go generate ./...

  6. Check new Go files in the folder template, templates will be converted to:

    1. template/wrapper.gtt -> template/wrapper.gtt.go:
      package templates
      
      import (
          "context"
          "github.com/go-qbit/template/filter"
          "io"
      )
      
      var (
          sc9e1fc75ad64f59917915544d65154cf = []byte{0x3c, 0x21, 0x44, 0x4f, 0x43, 0x54, 0x59, 0x50, 0x45, 0x20, 0x68, 0x74, 0x6d, 0x6c, 0x3e, 0xa, 0x3c, 0x68, 0x74, 0x6d, 0x6c, 0x3e, 0xa, 0x20, 0x20, 0x20, 0x20, 0x3c, 0x68, 0x65, 0x61, 0x64, 0x3e, 0xa, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3c, 0x74, 0x69, 0x74, 0x6c, 0x65, 0x3e}
          sa25bcc91ec51d6fea14a629de184814c = []byte{0x3c, 0x2f, 0x74, 0x69, 0x74, 0x6c, 0x65, 0x3e, 0xa, 0x20, 0x20, 0x20, 0x20, 0x3c, 0x2f, 0x68, 0x65, 0x61, 0x64, 0x3e, 0xa, 0x20, 0x20, 0x20, 0x20, 0x3c, 0x62, 0x6f, 0x64, 0x79, 0x3e}
          s33e48fc8e2ea8a4250506db7e0be31fd = []byte{0x3c, 0x2f, 0x3c, 0x62, 0x6f, 0x64, 0x79, 0x3e, 0xa, 0x3c, 0x2f, 0x68, 0x74, 0x6d, 0x6c, 0x3e}
      )
      
      func Wrapperpage(ctx context.Context, w io.Writer, tplClbF func(), caption string) {
          w.Write(sc9e1fc75ad64f59917915544d65154cf)
          io.WriteString(w, filter.Filterhtml(caption))
          w.Write(sa25bcc91ec51d6fea14a629de184814c)
          tplClbF()
          w.Write(s33e48fc8e2ea8a4250506db7e0be31fd)
      }
      
    2. template/index.gtt -> template/index.gtt.go:
      package template
      
      import (
          "context"
          "github.com/go-qbit/template/filter"
          "github.com/go-qbit/template/utils"
          "io"
      )
      
      var (
          s4da1a46ec20cf93ee5c846a51e04f0ed = []byte{0x3c, 0x70, 0x3e}
          s627661c621eab1b7b298abc47d1a250d = []byte{0x4d, 0x61, 0x6e}
          s5276343758bbfb9e0a374c9dd2fa6ce7 = []byte{0x57, 0x6f, 0x6d, 0x61, 0x6e}
          s921c704d576fc50eafc928f28d287019 = []byte{0x29, 0xa, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3c, 0x2f, 0x70, 0x3e}
          sa5c0aa5a33c99f4179eb48443e8bb33c = []byte{0x3c, 0x68, 0x31, 0x3e}
          s2b7c41aee73401e8cd970fba4c3bd4bd = []byte{0x3c, 0x2f, 0x68, 0x31, 0x3e, 0xa, 0x20, 0x20, 0x20, 0x20, 0x3c, 0x68, 0x72, 0x3e}
          s853ae90f0351324bd73ea615e6487517 = []byte{0x3a}
          s84c40473414caf2ed4a7b1283e48bbf4 = []byte{0x28}
          s7215ee9c7d9dc229d2921a40e899ec5f = []byte{0x20}
      )
      
      func ProcessTest(ctx context.Context, w io.Writer, header string, users []User) {
          Wrapperpage(ctx, w, func() {
              w.Write(sa5c0aa5a33c99f4179eb48443e8bb33c)
              io.WriteString(w, Filterhtml(header))
              w.Write(s2b7c41aee73401e8cd970fba4c3bd4bd)
              for _, user := range users {
                  w.Write(s4da1a46ec20cf93ee5c846a51e04f0ed)
                  ProcessUserName(ctx, w, user)
                  w.Write(s853ae90f0351324bd73ea615e6487517)
                  io.WriteString(w, utils.ToString(user.Age))
                  w.Write(s84c40473414caf2ed4a7b1283e48bbf4)
                  if user.IsMan {
                      w.Write(s627661c621eab1b7b298abc47d1a250d)
                  } else {
                      w.Write(s5276343758bbfb9e0a374c9dd2fa6ce7)
                  }
                  w.Write(s921c704d576fc50eafc928f28d287019)
              }
          }, header)
      }
      
      func ProcessUserName(ctx context.Context, w io.Writer, user User) {
          io.WriteString(w, Filterhtml(user.Name))
          w.Write(s7215ee9c7d9dc229d2921a40e899ec5f)
          io.WriteString(w, Filterhtml(user.Lastname))
      }
      
  7. Run the application: go run main.go

Syntax

Intro

Template directives are embedded between tags [% and %].

[% IF a == b %]
    text
[% END %]

Several directives within one block must be splitted by ;.

[% 
    IF a == b;
        FOR v IN array;
            v;
        END;
    END 
%]

You can use multiline comments within tags:

[% a := 10 /* comment */ %]
[% /*
    Multiline
    comment
*/ %]

By default whitespaces around tags is chomped. The code

Before
[% v1 %] [% v2 %]
After

will produce BeforeV1V2After if v1 == "V1" and v2 == "V2". To save whitespaces use tag [%+ to save left whitespaces and +%] to save right whitespaces. The code

Before
[%+ v1 +%] [% v2 +%]
After

will produce

Before
V1 V2
After

if v1 == "V1" and v2 == "V2".

Directives

IMPORT

The IMPORT directive declares a list of go packages that will be added to result Go file. Packages must be quoted by " and splitted by ",". It's optional, but tt must be first directive in a template file if you add it.

[% 
    IMPORT(
        "package1",
        "package2"
    )
%]
TEMPLATE

The TEMPLATE directive defines a new template:

 [% TEMPLATE <name>(<parameters_list>) USE WRAPPER <wrapper_name>(<parameters_list>) %]
    Template content
 [% END %]

USE WRAPPER is optional, see WRAPPER for more information.

WRAPPER

The WRAPPER directive defines a new template wrapper. The place for content must be declared by CONTENT. You can use wrappers to define common parts of templates, for example web site header and footer.

[% WRAPPER page(title string) %]
<!DOCTYPE html>
<html lang="ru">
    <head>
        <title>[% title | html %]</title>
    </head>
    <body>
        [% CONTENT %]
    </body>
</html>
[% END %]

Also you can use WRAPPER for WRAPPER:

[% WRAPPER page(title string) USE WRAPPER outer() %]
    [% CONTENT %]
[% END %]
PROCESS

The PROCESS directive inserts output of other template to current.

[% PROCESS <template_name>(parameters) %]
IF / ELSE

The IF / ELSE can be used to process or ignore a block based on some run-time condition.

[% IF a < 10 %]
    Less
[% ELSE %]
    Greater or equal
[% END %]
FOR

The FOR directive will iterate through the items in a list/map

[% FOR item IN list %]
    [% item | html %]
[% END %]

[% FOR i, item IN list %]
    [% i %]: [% item | html %]
[% END %]

[% FOR key IN map %]
    [% key | html %]
[% END %]

[% FOR key, value IN map %]
    [% key | html %]: [% value | html %]
[% END %]

or while the last expression of the three is true

[% FOR i:=0; i<100; i++ %]
    [% i %]
[% END %]

Filters

Any expression can be processed through filter before output

[% varName | filterName1 %]
[% (a + b) | filterName2(10) %]
html

The html filter escaped dangerous character

Operators

Assignments
  1. =
  2. :=
Comparison
  1. >, GT
  2. <, LT
  3. >=, GE
  4. <=, LE
  5. ==, EQ
Mathematical
  1. +
  2. -
  3. *
  4. /
  5. %
Boolean
  1. &&, AND
  2. ||, OR
Unary
  1. !, NOT
  2. ++
  3. --

Documentation

Index

Constants

View Source
const AND = 57366
View Source
const ASSIGNMENT = 57368
View Source
const COMMENT = 57371
View Source
const CONTENT_MARKER = 57359
View Source
const DEC = 57370
View Source
const ELSE = 57352
View Source
const END = 57353
View Source
const EQ = 57361
View Source
const FOR = 57349
View Source
const GE = 57363
View Source
const IDENTIFIER = 57346
View Source
const IF = 57351
View Source
const IMPORT = 57356
View Source
const IN = 57350
View Source
const INC = 57369
View Source
const LE = 57364
View Source
const NE = 57362
View Source
const NOT = 57367
View Source
const NUMBER = 57348
View Source
const OR = 57365
View Source
const PROCESS = 57360
View Source
const STRING = 57347
View Source
const TEMPLATE = 57355
View Source
const USE = 57358
View Source
const VARS = 57354
View Source
const WRAPPER = 57357

Variables

This section is empty.

Functions

This section is empty.

Types

type GenGoOpts

type GenGoOpts struct {
	PackageName string
	Imports     []string
	FileName    string
}

type Template

type Template struct {
	// contains filtered or unexported fields
}

func New

func New() *Template

func (*Template) Parse

func (t *Template) Parse(text string) error

func (*Template) ParseFile

func (t *Template) ParseFile(filename string) error

func (*Template) WriteGo

func (t *Template) WriteGo(w io.Writer, packageName, fileNme string)

Directories

Path Synopsis
test

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL