Fast, powerful, yet easy to use template engine for Go. Optimized for speed, zero memory allocations in hot paths. Up to 20x faster than html/template

Overview

Build Status GoDoc Go Report Card

quicktemplate

A fast, powerful, yet easy to use template engine for Go. Inspired by the Mako templates philosophy.

Features

  • Extremely fast. Templates are converted into Go code and then compiled.
  • Quicktemplate syntax is very close to Go - there is no need to learn yet another template language before starting to use quicktemplate.
  • Almost all bugs are caught during template compilation, so production suffers less from template-related bugs.
  • Easy to use. See quickstart and examples for details.
  • Powerful. Arbitrary Go code may be embedded into and mixed with templates. Be careful with this power - do not query the database and/or external resources from templates unless you miss the PHP way in Go :) This power is mostly for arbitrary data transformations.
  • Easy to use template inheritance powered by Go interfaces. See this example for details.
  • Templates are compiled into a single binary, so there is no need to copy template files to the server.

Drawbacks

  • Templates cannot be updated on the fly on the server, since they are compiled into a single binary. Take a look at fasttemplate if you need a fast template engine for simple dynamically updated templates. There are ways to dynamically update the templates during development.

Performance comparison with html/template

Quicktemplate is more than 20x faster than html/template. The following simple template is used in the benchmark:

Benchmark results:

$ go test -bench='Benchmark(Quick|HTML)Template' -benchmem github.com/valyala/quicktemplate/tests
BenchmarkQuickTemplate1-4                 	10000000	       120 ns/op	       0 B/op	       0 allocs/op
BenchmarkQuickTemplate10-4                	 3000000	       441 ns/op	       0 B/op	       0 allocs/op
BenchmarkQuickTemplate100-4               	  300000	      3945 ns/op	       0 B/op	       0 allocs/op
BenchmarkHTMLTemplate1-4                  	  500000	      2501 ns/op	     752 B/op	      23 allocs/op
BenchmarkHTMLTemplate10-4                 	  100000	     12442 ns/op	    3521 B/op	     117 allocs/op
BenchmarkHTMLTemplate100-4                	   10000	    123392 ns/op	   34498 B/op	    1152 allocs/op

goTemplateBenchmark compares QuickTemplate with numerous Go templating packages. QuickTemplate performs favorably.

Security

  • All template placeholders are HTML-escaped by default.
  • Template placeholders for JSON strings prevent from </script>-based XSS attacks:
{% func FailedXSS() %}
<script>
    var s = {%q= "</script><script>alert('you pwned!')" %};
</script>
{% endfunc %}

Examples

See examples.

Quick start

First of all, install the quicktemplate package and quicktemplate compiler (qtc):

go get -u github.com/valyala/quicktemplate
go get -u github.com/valyala/quicktemplate/qtc

If you using go generate, you just need put following into your main.go

Important: please specify your own folder (-dir) to generate template file

//go:generate go get -u github.com/valyala/quicktemplate/qtc
//go:generate qtc -dir=app/views  

Let's start with a minimal template example:

All text outside function templates is treated as comments,
i.e. it is just ignored by quicktemplate compiler (`qtc`). It is for humans.

Hello is a simple template function.
{% func Hello(name string) %}
	Hello, {%s name %}!
{% endfunc %}

Save this file into a templates folder under the name hello.qtpl and run qtc inside this folder.

If everything went OK, hello.qtpl.go file should appear in the templates folder. This file contains Go code for hello.qtpl. Let's use it!

Create a file main.go outside templates folder and put the following code there:

package main

import (
	"fmt"

	"./templates"
)

func main() {
	fmt.Printf("%s\n", templates.Hello("Foo"))
	fmt.Printf("%s\n", templates.Hello("Bar"))
}

Then issue go run. If everything went OK, you'll see something like this:


	Hello, Foo!


	Hello, Bar!

Let's create more a complex template which calls other template functions, contains loops, conditions, breaks, continues and returns. Put the following template into templates/greetings.qtpl:


Greetings greets up to 42 names.
It also greets John differently comparing to others.
{% func Greetings(names []string) %}
	{% if len(names) == 0 %}
		Nobody to greet :(
		{% return %}
	{% endif %}

	{% for i, name := range names %}
		{% if i == 42 %}
			I'm tired to greet so many people...
			{% break %}
		{% elseif name == "John" %}
			{%= sayHi("Mr. " + name) %}
			{% continue %}
		{% else %}
			{%= Hello(name) %}
		{% endif %}
	{% endfor %}
{% endfunc %}

sayHi is unexported, since it starts with lowercase letter.
{% func sayHi(name string) %}
	Hi, {%s name %}
{% endfunc %}

Note that every template file may contain an arbitrary number
of template functions. For instance, this file contains Greetings and sayHi
functions.

Run qtc inside templates folder. Now the folder should contain two files with Go code: hello.qtpl.go and greetings.qtpl.go. These files form a single templates Go package. Template functions and other template stuff is shared between template files located in the same folder. So Hello template function may be used inside greetings.qtpl while it is defined in hello.qtpl. Moreover, the folder may contain ordinary Go files, so its contents may be used inside templates and vice versa. The package name inside template files may be overriden with {% package packageName %}.

Now put the following code into main.go:

package main

import (
	"bytes"
	"fmt"

	"./templates"
)

func main() {
	names := []string{"Kate", "Go", "John", "Brad"}

	// qtc creates Write* function for each template function.
	// Such functions accept io.Writer as first parameter:
	var buf bytes.Buffer
	templates.WriteGreetings(&buf, names)

	fmt.Printf("buf=\n%s", buf.Bytes())
}

Careful readers may notice different output tags were used in these templates: {%s name %} and {%= Hello(name) %}. What's the difference? The {%s x %} is used for printing HTML-safe strings, while {%= F() %} is used for embedding template function calls. Quicktemplate supports also other output tags:

  • {%d int %} and {%dl int64 %} {%dul uint64 %} for integers.
  • {%f float %} for float64. Floating point precision may be set via {%f.precision float %}. For example, {%f.2 1.2345 %} outputs 1.23.
  • {%z bytes %} for byte slices.
  • {%q str %} and {%qz bytes %} for JSON-compatible quoted strings.
  • {%j str %} and {%jz bytes %} for embedding str into a JSON string. Unlike {%q str %}, it doesn't quote the string.
  • {%u str %} and {%uz bytes %} for URL encoding the given str.
  • {%v anything %} is equivalent to %v in printf-like functions.

All the output tags except {%= F() %} produce HTML-safe output, i.e. they escape < to &lt;, > to &gt;, etc. If you don't want HTML-safe output, then just put = after the tag. For example: {%s= "<h1>This h1 won't be escaped</h1>" %}.

As you may notice {%= F() %} and {%s= F() %} produce the same output for {% func F() %}. But the first one is optimized for speed - it avoids memory allocations and copies. It is therefore recommended to stick to it when embedding template function calls.

Additionally, the following extensions are supported for {%= F() %}:

  • {%=h F() %} produces html-escaped output.
  • {%=u F() %} produces URL-encoded output.
  • {%=q F() %} produces quoted json string.
  • {%=j F() %} produces json string without quotes.
  • {%=uh F() %} produces html-safe URL-encoded output.
  • {%=qh F() %} produces html-safe quoted json string.
  • {%=jh F() %} produces html-safe json string without quotes.

All output tags except {%= F() %} family may contain arbitrary valid Go expressions instead of just an identifier. For example:

Import fmt for fmt.Sprintf()
{% import "fmt" %}

FmtFunc uses fmt.Sprintf() inside output tag
{% func FmtFunc(s string) %}
	{%s fmt.Sprintf("FmtFunc accepted %q string", s) %}
{% endfunc %}

There are other useful tags supported by quicktemplate:

  • {% comment %}

    {% comment %}
        This is a comment. It won't trap into the output.
        It may contain {% arbitrary tags %}. They are just ignored.
    {% endcomment %}
    
  • {% plain %}

    {% plain %}
        Tags will {% trap into %} the output {% unmodified %}.
        Plain block may contain invalid and {% incomplete tags.
    {% endplain %}
    
  • {% collapsespace %}

    {% collapsespace %}
        <div>
            <div>space between lines</div>
               and {%s "tags" %}
             <div>is collapsed into a single space
             unless{% newline %}or{% space %}is used</div>
        </div>
    {% endcollapsespace %}
    

    Is converted into:

    <div> <div>space between lines</div> and tags <div>is collapsed into a single space unless
    or is used</div> </div>
    
  • {% stripspace %}

    {% stripspace %}
         <div>
             <div>space between lines</div>
                and {%s " tags" %}
             <div>is removed unless{% newline %}or{% space %}is used</div>
         </div>
    {% endstripspace %}
    

    Is converted into:

    <div><div>space between lines</div>and tags<div>is removed unless
    or is used</div></div>
    
  • It is possible removing whitespace before and after the tag by adding - after {% or prepending %} with -. For example:

    var sum int
    {%- for i := 1; i <= 3; i++ -%}
    sum += {%d i %}
    {%- endfor -%}
    return sum
    

    Is converted into:

    var sum int
    sum += 1
    sum += 2
    sum += 3
    return sum
    
  • {% switch %}, {% case %} and {% default %}:

    1 + 1 =
    {% switch 1+1 %}
    {% case 2 %}
    2?
    {% case 42 %}
    42!
    {% default %}
        I don't know :(
    {% endswitch %}
    
  • {% code %}:

    {% code
    // arbitrary Go code may be embedded here!
    type FooArg struct {
        Name string
        Age int
    }
    %}
    
  • {% package %}:

    Override default package name with the custom name
    {% package customPackageName %}
    
  • {% import %}:

    Import external packages.
    {% import "foo/bar" %}
    {% import (
        "foo"
        bar "baz/baa"
    ) %}
    
  • {% cat "/path/to/file" %}:

    Cat emits the given file contents as a plaintext:
    {% func passwords() %}
        /etc/passwd contents:
        {% cat "/etc/passwd" %}
    {% endfunc %}
    
  • {% interface %}:

    Interfaces allow powerful templates' inheritance
    {%
    interface Page {
        Title()
        Body(s string, n int)
        Footer()
    }
    %}
    
    PrintPage prints Page
    {% func PrintPage(p Page) %}
        <html>
            <head><title>{%= p.Title() %}</title></head>
            <body>
                <div>{%= p.Body("foo", 42) %}</div>
                <div>{%= p.Footer() %}</div>
            </body>
        </html>
    {% endfunc %}
    
    Base page implementation
    {% code
    type BasePage struct {
        TitleStr string
        FooterStr string
    }
    %}
    {% func (bp *BasePage) Title() %}{%s bp.TitleStr %}{% endfunc %}
    {% func (bp *BasePage) Body(s string, n int) %}
        <b>s={%q s %}, n={%d n %}</b>
    {% endfunc %}
    {% func (bp *BasePage) Footer() %}{%s bp.FooterStr %}{% endfunc %}
    
    Main page implementation
    {% code
    type MainPage struct {
        // inherit from BasePage
        BasePage
    
        // real body for main page
        BodyStr string
    }
    %}
    
    Override only Body
    Title and Footer are used from BasePage.
    {% func (mp *MainPage) Body(s string, n int) %}
        <div>
            main body: {%s mp.BodyStr %}
        </div>
        <div>
            base body: {%= mp.BasePage.Body(s, n) %}
        </div>
    {% endfunc %}
    

    See basicserver example for more details.

Performance optimization tips

  • Prefer calling WriteFoo instead of Foo when generating template output for {% func Foo() %}. This avoids unnesessary memory allocation and a copy for a string returned from Foo().

  • Prefer {%= Foo() %} instead of {%s= Foo() %} when embedding a function template {% func Foo() %}. Though both approaches generate identical output, the first approach is optimized for speed.

  • Prefer using existing output tags instead of passing fmt.Sprintf to {%s %}. For instance, use {%d num %} instead of {%s fmt.Sprintf("%d", num) %}, because the first approach is optimized for speed.

  • Prefer using specific output tags instead of generic output tag {%v %}. For example, use {%s str %} instead of {%v str %}, since specific output tags are optimized for speed.

  • Prefer creating custom function templates instead of composing complex strings by hands before passing them to {%s %}. For instance, the first approach is slower than the second one:

    {% func Foo(n int) %}
        {% code
        // construct complex string
        complexStr := ""
        for i := 0; i < n; i++ {
            complexStr += fmt.Sprintf("num %d,", i)
        }
        %}
        complex string = {%s= complexStr %}
    {% endfunc %}
    
    {% func Foo(n int) %}
        complex string = {%= complexStr(n) %}
    {% endfunc %}
    
    // Wrap complexStr func into stripspace for stripping unnesessary space
    // between tags and lines.
    {% stripspace %}
    {% func complexStr(n int) %}
        {% for i := 0; i < n; i++ %}
            num{% space %}{%d i %}{% newline %}
        {% endfor %}
    {% endfunc %}
    {% endstripspace %}
    
  • Make sure that the io.Writer passed to Write* functions is buffered. This will minimize the number of write syscalls, which may be quite expensive.

    Note: There is no need to wrap fasthttp.RequestCtx into bufio.Writer, since it is already buffered.

  • Profile your programs for memory allocations and fix the most demanding functions based on the output of go tool pprof --alloc_objects.

Use cases

While the main quicktemplate purpose is generating HTML, it may be used for generating other data too. For example, JSON and XML marshalling may be easily implemented with quicktemplate:

{% code
type MarshalRow struct {
	Msg string
	N int
}

type MarshalData struct {
	Foo int
	Bar string
	Rows []MarshalRow
}
%}

// JSON marshaling
{% stripspace %}
{% func (d *MarshalData) JSON() %}
{
	"Foo": {%d d.Foo %},
	"Bar": {%q= d.Bar %},
	"Rows":[
		{% for i, r := range d.Rows %}
			{
				"Msg": {%q= r.Msg %},
				"N": {%d r.N %}
			}
			{% if i + 1 < len(d.Rows) %},{% endif %}
		{% endfor %}
	]
}
{% endfunc %}
{% endstripspace %}

// XML marshalling
{% stripspace %}
{% func (d *MarshalData) XML() %}
<MarshalData>
	<Foo>{%d d.Foo %}</Foo>
	<Bar>{%s d.Bar %}</Bar>
	<Rows>
	{% for _, r := range d.Rows %}
		<Row>
			<Msg>{%s r.Msg %}</Msg>
			<N>{%d r.N %}</N>
		</Row>
	{% endfor %}
	</Rows>
</MarshalData>
{% endfunc %}
{% endstripspace %}

Usually, marshalling built with quicktemplate works faster than the marshalling implemented via standard encoding/json and encoding/xml. See the corresponding benchmark results:

go test -bench=Marshal -benchmem github.com/valyala/quicktemplate/tests
BenchmarkMarshalJSONStd1-4                	 3000000	       480 ns/op	       8 B/op	       1 allocs/op
BenchmarkMarshalJSONStd10-4               	 1000000	      1842 ns/op	       8 B/op	       1 allocs/op
BenchmarkMarshalJSONStd100-4              	  100000	     15820 ns/op	       8 B/op	       1 allocs/op
BenchmarkMarshalJSONStd1000-4             	   10000	    159327 ns/op	      59 B/op	       1 allocs/op
BenchmarkMarshalJSONQuickTemplate1-4      	10000000	       162 ns/op	       0 B/op	       0 allocs/op
BenchmarkMarshalJSONQuickTemplate10-4     	 2000000	       748 ns/op	       0 B/op	       0 allocs/op
BenchmarkMarshalJSONQuickTemplate100-4    	  200000	      6572 ns/op	       0 B/op	       0 allocs/op
BenchmarkMarshalJSONQuickTemplate1000-4   	   20000	     66784 ns/op	      29 B/op	       0 allocs/op
BenchmarkMarshalXMLStd1-4                 	 1000000	      1652 ns/op	       2 B/op	       2 allocs/op
BenchmarkMarshalXMLStd10-4                	  200000	      7533 ns/op	      11 B/op	      11 allocs/op
BenchmarkMarshalXMLStd100-4               	   20000	     65763 ns/op	     195 B/op	     101 allocs/op
BenchmarkMarshalXMLStd1000-4              	    2000	    663373 ns/op	    3522 B/op	    1002 allocs/op
BenchmarkMarshalXMLQuickTemplate1-4       	10000000	       145 ns/op	       0 B/op	       0 allocs/op
BenchmarkMarshalXMLQuickTemplate10-4      	 3000000	       597 ns/op	       0 B/op	       0 allocs/op
BenchmarkMarshalXMLQuickTemplate100-4     	  300000	      5833 ns/op	       0 B/op	       0 allocs/op
BenchmarkMarshalXMLQuickTemplate1000-4    	   30000	     53000 ns/op	      32 B/op	       0 allocs/op

FAQ

  • Why is the quicktemplate syntax incompatible with html/template?

    Because html/template syntax isn't expressive enough for quicktemplate.

  • What's the difference between quicktemplate and ego?

    Ego is similar to quicktemplate in the sense it converts templates into Go code. But it misses the following stuff, which makes quicktemplate so powerful and easy to use:

    • Defining multiple function templates in a single template file.
    • Embedding function templates inside other function templates.
    • Template interfaces, inheritance and overriding. See this example for details.
    • Top-level comments outside function templates.
    • Template packages.
    • Combining arbitrary Go files with template files in template packages.
    • Performance optimizations.
  • What's the difference between quicktemplate and gorazor?

    Gorazor is similar to quicktemplate in the sense it converts templates into Go code. But it misses the following useful features:

    • Clear syntax instead of hard-to-understand magic stuff related to template arguments, template inheritance and embedding function templates into other templates.
  • Is there a syntax highlighting for qtpl files?

    Yes - see this issue for details. If you are using JetBrains products (syntax highlighting and autocomplete):

  • I didn't find an answer for my question here.

    Try exploring these questions.

Comments
  • cat in func with parameters

    cat in func with parameters

    I'm trying to understand cat.

    In readme I can read:

    {% cat "/path/to/file" %}:
    
    Cat emits the given file contents as a plaintext:
    {% func passwords() %}
        /etc/passwd contents:
        {% cat "/etc/passwd" %}
    {% endfunc %}
    

    I'm trying to use something like this but with a parameter:

    {% func passwords(user string) %}
        /etc/passwd contents for user:
        {% cat "/etc/" + user + "/passwd" %}
    {% endfunc %}
    

    But the compiler returns an error: invalid syntax.

    How can I do? Is it possible?

    question 
    opened by frederikhors 8
  • Suggestion qtc: Add a watcher qtc -w

    Suggestion qtc: Add a watcher qtc -w

    Add a watcher subcommand/flag for example qtc -w ./ -d ./templates -> watch and compile on file changes in the current directory, serve the compiled files in the ./templates directory.

    You can use fsnotify package, I will do that on iris but it will be nice to have it build'n with qtc :)

    P.S: I don't know if go generate has a watch command but I doubt

    enhancement question 
    opened by ghost 8
  • Add flag to not have the comments in the qtpl.go file

    Add flag to not have the comments in the qtpl.go file

    Is it possible to add a flag that will not add the comments in the qtpl.go file? Because at the moment for some reason the comment lines are bugging with my golintci-lint. Another option would be to add a space between the // and the first letter of the comment.

    so instead of //line internal/.....qtpl:1 it would become // line internal/....qtpl:1

    enhancement 
    opened by ChielTimmermans 7
  • Refactoring

    Refactoring "parser" to separate package

    This refactors the parser into a separate package, so that it can be used by third-party build tools that also use quicktemplate. This eliminates the need to build a binary for generating Go code.

    opened by kenshaw 7
  • New VS Code quicktemplate language definition

    New VS Code quicktemplate language definition

    I made a quicktemplate VS Code language extension. It's very simple, just basic syntax highlighting.

    https://marketplace.visualstudio.com/items?itemName=vsatomi.vscode-quicktemplate#overview

    Thanks.

    opened by atomi 5
  • Hash in files name but not in development

    Hash in files name but not in development

    Coming from javascript frontend world I'm wondering how to use hash when importing or referencing files in templates.

    I wanna develop with this code:

    {% func Page(p Page) %}
      <html>
      <head>
        <link rel="stylesheet" href="/static/css/base.css"/>
      </head>
      <body>
        {%= p.Body() %}
      </body>
      </html>
    {% endfunc %}
    

    and deploy with this code:

    {% func Page(p Page) %}
      <html>
      <head>
        <link rel="stylesheet" href="/static/css/base-4ab5f2de4.css"/>
      </head>
      <body>
        {%= p.Body() %}
      </body>
      </html>
    {% endfunc %}
    
    • before: base.css
    • after: base-4ab5f2de4.css

    Is it possible today?

    • What do you think about using an ENV VAR at compile time to switch behaviour (DEVELOP/PRODUCTION) and calculate every hash with a function?

    • What do you use today for cache invalidation?

    This is useful also for adding CDN addresses in future, right?

    Something similar (abandoned): https://github.com/defrankland/hasherator.

    question 
    opened by frederikhors 4
  • Feature Request: Change package name

    Feature Request: Change package name

    First off, thanks for the great template library. Coming from mako, I feel right at home with quicktemplate.

    Currently quicktemplate only outputs the name of the directory as the package name in the generated go code. Would it be possible to allow the package name to be changed from a {% package %} directive at the top of the template?

    My use case is that I have a few templates that I want to drop into the main package alongside other code. I'd like to be able to specify {% package "main" %}

    I surveyed the code to take a look at how to implement it. I guess the packageName would have to be exposed by the scanner somehow to get it back up to the parser.

    enhancement 
    opened by jeremylowery 4
  • qtc: add separate logger for os.Stdout and os.Stderr

    qtc: add separate logger for os.Stdout and os.Stderr

    This PR adds a separate logger to qtc for logging informational messages called infoLogger and renames the current error logger to errorLogger.

    Previously, logger wrote to os.Stdout causing informational messages like qtc: 2021/03/29 20:21:48 Compiling *.qtpl template files in directory "web\\templates" to be sent to stderr which can be somewhat inconvenient.

    infoLogger outputs to os.Stdout and is used for informational statements (so anything calling Printf) and errorLogger outputs to os.Stderr and is used for actual error logging (anything calling Fatalf).

    Ta!

    opened by codemicro 3
  • don't work {% case []string %} inside {% switch r.(type) %}

    don't work {% case []string %} inside {% switch r.(type) %}

    Выдает такое: invalid statement "case []string" at file "views/templates/system/routeTable/table_row.qtpl", line 68, pos 37, token "[]string"

    вроде должно же штатно обработать? С одиночными типами работает только в путь

    bug 
    opened by ruslanBik4 3
  • [Feature Request] ignoring new line and tab indents in special tags

    [Feature Request] ignoring new line and tab indents in special tags

    I am using QTPL for go code generation. i see that it is intended for html template. But it can be very useful for all kind of text generation.

    issue #27 does not cover my case

    below is a sample template func to explain my use case

    {% func GenTestFunc() %}
    	func TestFunc(a int, b int) int {
    		var sum int
    		{% for i := 0; i < 10; i++ %}
    			sum += {%d i %}
    		{% endfor %}
    		return sum
    	}
    {% endfunc %}
    

    I'm getting:

    	func TestFunc(a int, b int) int {
    		var sum int
    		
    			sum += 0
    		
    			sum += 1
    		
    			sum += 2
    		
    			sum += 3
    		
    			sum += 4
    		
    			sum += 5
    		
    			sum += 6
    		
    			sum += 7
    		
    			sum += 8
    		
    			sum += 9
    
    		return sum
    		
    	}
    

    expect something like this:

    func TestFunc(a int, b int) int {
    	var sum int
    	sum += 0
    	sum += 1
    	sum += 2
    	sum += 3
    	sum += 4
    	sum += 5
    	sum += 6
    	sum += 7
    	sum += 8
    	sum += 9
    	return sum
    }
    

    i tried {% stripspace %} and {% collapsespace %} but they are not sufficient

    1. {% func %}, {% for %}, {% if %} and other tags, take string between as it is, to improve readability, these blocks can ignore first tab/space indent, or special tag to ignore them
    2. also each the block, create a new line before them

    i had to write this to get the intended output

    {% func GenTestFunc() %}
    func TestFunc(a int, b int) int {
    	var sum int{% for i := 0; i < 10; i++ %}
    	sum += {%d i %}{% endfor %}
    	return sum
    }
    {% endfunc %}
    
    enhancement 
    opened by muthukrishnan24 3
  • Include template

    Include template

    Thank you very much for the great job, Aliaksandr. I just was not able to find how to include another template into the current one (I have some standard repetitive parts in my templates). E.g. in the html/template package it is {{ template "FILENAME" }} construction.

    question 
    opened by ArtavazdAvetisyan 3
  • qtc binary is not installed by the command suggested by README

    qtc binary is not installed by the command suggested by README

    go get -u github.com/valyala/quicktemplate/qtc did not get qtc into my path; go install github.com/valyala/quicktemplate/qtc did.

    I use MacOS and my Go is version 1.19.2 installed via homebrew.

    opened by skaurus 0
  • Should a template define at least one function?

    Should a template define at least one function?

    Documentation says that template can "contain arbitrary number of functions". But is it a requirement?

    Say I don't need code reuse in my template. I just have some literal text inside {% %} block, and text of this block contains variables {%s strvar %} here and loops {% for _, v := range arr %}{%s v %}{% endfor %} there. Do I need to wrap this into some function? If not, what method do I call to get rendered result?

    Example:

    {%
    Some verbatim text of my template. Lorem ipsum maybe.
    But then I want to insert some {%s string %}.
    And even iterate over a loop:
    {% for i, v := arr %}
        {% if i < 5 %}{%s v %}{% endif %}
    {% endfor %}
    The end!
    %}
    

    Is this a legal template?

    opened by skaurus 0
  • Security: templates are vulnerable to XSS

    Security: templates are vulnerable to XSS

    Escaping is intentionally not contextual. As the security section states the only supported automatic escaping is HTML-based (link). This means that any use of this template that interpolates user-controlled data in a different context is vulnerable to XSS.

    Here is one example:

    <img onclick="{{interpolating action}}">
    

    If the interpolating action outputs something like "javascript:alert(1)" the code will be executed.

    Please add a section to the security paragraph of the README documenting that quicktemplate is not secure to use. As far as in understand this package only supports manual escaping, and only for specific kinds of escaping, and this leads to vulnerable templates.

    As an alternative, implement contextual autoescaping. As a reference for autoescaping and documentation on how it works you can take a look at the standard library security model: https://pkg.go.dev/html/template#hdr-Security_Model. Disclaimer: this is not easy to do and I think it is beyond the scope of this package.

    Please let me know if you need any assistance or explanation about the threats and potential dangers of using this library as it is today, I'd be happy to help :)

    opened by empijei 0
  • Bump github.com/valyala/fasthttp from 1.30.0 to 1.34.0

    Bump github.com/valyala/fasthttp from 1.30.0 to 1.34.0

    Bumps github.com/valyala/fasthttp from 1.30.0 to 1.34.0.

    Release notes

    Sourced from github.com/valyala/fasthttp's releases.

    v1.34.0

    • 59f94a3 Update github.com/klauspost/compress (#1237) (Mikhail Faraponov)
    • 62c15a5 Don't reset RequestCtx.s (#1234) (Erik Dubbelboer)
    • 7670c6e Fix windows tests (#1235) (Erik Dubbelboer)
    • f54ffa1 feature: Keep the memory usage of the service at a stable level (#1216) (Rennbon)
    • 15262ec Warn about unsafe ServeFile usage (#1228) (Erik Dubbelboer)
    • 1116d03 Fix panic while reading invalid trailers (Erik Dubbelboer)
    • 856ca8e Update dependencies (#1230) (Mikhail Faraponov)
    • 6b5bc7b Add windows support to normalizePath (Erik Dubbelboer)
    • f0b0cfe Don't log ErrBadTrailer by default (Erik Dubbelboer)
    • 6937fee fix: (useless check), skip Response body if http method HEAD (#1224) (Pavel Burak)
    • b85d2a2 Fix http proxy behavior (#1221) (Aoang)
    • ad8a07a RequestHeader support set no default ContentType (#1218) (Jack.Ju)
    • c94581c support configure HostClient (#1214) (lin longhjui)
    • 632e222 Client examples (#1208) (Sergey Ponomarev)
    • 6a3cc23 uri_test.go use example.com for clearness (#1212) (Sergey Ponomarev)
    • 9d665e0 Update dependencies (#1204) (Mikhail Faraponov)
    • 8d7953e Fix scheme check for not yet parsed requests (#1203) (ArminBTVS)

    v1.33.0

    • 61aa8b1 remove redundant code (#1202) (tyltr)
    • 4369776 fix(hijack): reuse RequestCtx (#1201) (Sergio VS)
    • 2aca3e8 fix(hijack): reset userValues after hijack handler execution (#1199) (Sergio VS)
    • 9123060 Updated dependencies (#1194) (Mikhail Faraponov)

    v1.32.0

    • 7eeb00e Make tests less flaky (#1189) (Erik Dubbelboer)
    • d19b872 Update tcpdialer.go (#1188) (Mikhail Faraponov)
    • c727b99 Release UseHostHeader in ReleaseRequest() (#1185) (Tolyar)
    • 6c0518b Fix UseHostHeader for DoTimeout + tests (#1184) (Tolyar)
    • 6b55811 Add MaxIdleWorkerDuration to Server. (#1183) (Kilos Liu)
    • 4517204 Allow to set Host header for Client (#1169) (Tolyar)
    • 258a4c1 fix: reset response after reset user values on keep-alive connections (#1176) (Sergio VS)
    • e9db537 Use %w to wrap errors (#1175) (Erik Dubbelboer)
    • 7db0597 Fix bad request trailer panic (Erik Dubbelboer)
    • 4aadf9a Fix parseTrailer panic (Erik Dubbelboer)
    • da7ff7a Add trailer support (#1165) (ichx)
    • 017f0aa fix: reset request after reset user values on keep-alive connections (#1162) (Sergio VS)
    • 3b117f8 feat: close idle connections when server shutdown (#1155) (ichx)
    • a94a2c3 Remove redundant code (#1154) (ichx)
    • f7c354c Fix race condition in Client.mCleaner (Erik Dubbelboer)
    • c078a9d Add string and bytes buffer convert trick in README (#1151) (ichx)
    • 3ff6aaa uri: isHttps() and isHttp() (#1150) (Sergey Ponomarev)
    • 8febad0 http.go: Request.SetURI() (Fix #1141) (#1148) (Sergey Ponomarev)
    • 2ca01c7 fix: Status Line parsing and writing (#1135) (Shivansh Vij)
    • 931d0a4 Fix lint (Erik Dubbelboer)
    • d613502 use sync.map is better (#1145) (halst)
    • c15e642 Don't run all race tests on windows (#1143) (Erik Dubbelboer)
    • 6006c87 chore (#1137) (tyltr)
    • 6d4db9b Fix race condition in getTCPAddrs (Erik Dubbelboer)

    ... (truncated)

    Commits

    Dependabot compatibility score

    Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting @dependabot rebase.


    Dependabot commands and options

    You can trigger Dependabot actions by commenting on this PR:

    • @dependabot rebase will rebase this PR
    • @dependabot recreate will recreate this PR, overwriting any edits that have been made to it
    • @dependabot merge will merge this PR after your CI passes on it
    • @dependabot squash and merge will squash and merge this PR after your CI passes on it
    • @dependabot cancel merge will cancel a previously requested merge and block automerging
    • @dependabot reopen will reopen this PR if it is closed
    • @dependabot close will close this PR and stop Dependabot recreating it. You can achieve the same result by closing it manually
    • @dependabot ignore this major version will close this PR and stop Dependabot creating any more for this major version (unless you reopen the PR or upgrade to it yourself)
    • @dependabot ignore this minor version will close this PR and stop Dependabot creating any more for this minor version (unless you reopen the PR or upgrade to it yourself)
    • @dependabot ignore this dependency will close this PR and stop Dependabot creating any more for this dependency (unless you reopen the PR or upgrade to it yourself)
    • @dependabot use these labels will set the current labels as the default for future PRs for this repo and language
    • @dependabot use these reviewers will set the current reviewers as the default for future PRs for this repo and language
    • @dependabot use these assignees will set the current assignees as the default for future PRs for this repo and language
    • @dependabot use this milestone will set the current milestone as the default for future PRs for this repo and language

    You can disable automated security fix PRs for this repo from the Security Alerts page.

    dependencies 
    opened by dependabot[bot] 0
  • Go language server ignores the compiled templates

    Go language server ignores the compiled templates

    Hi, valyala!

    I have used the quicktemplate for a while, and it works great! But there is an issue that bothers me a lot; the language server would always ignore the compiled code generated by the command qtc.

    So that I can't use jump to the definition or get the parameter hint of the functions.

    Here is an example of the project structure:

    ./demo
    |--templates
        |--config.qtpl
        |--config.qtpl.go
    |--main.go
    |--go.mod
    

    Any ideas?

    opened by pot-code 0
Owner
Aliaksandr Valialkin
Working on @VictoriaMetrics
Aliaksandr Valialkin
A handy, fast and powerful go template engine.

Hero Hero is a handy, fast and powerful go template engine, which pre-compiles the html templates to go code. It has been used in production environme

Lime 1.5k Nov 20, 2022
Wrapper package for Go's template/html to allow for easy file-based template inheritance.

Extemplate Extemplate is a small wrapper package around html/template to allow for easy file-based template inheritance. File: templates/parent.tmpl <

Danny van Kooten 51 Nov 13, 2022
The world’s most powerful template engine and Go embeddable interpreter.

The world’s most powerful template engine and Go embeddable interpreter

Open2b 368 Nov 26, 2022
HTML template engine for Go

Ace - HTML template engine for Go Overview Ace is an HTML template engine for Go. This is inspired by Slim and Jade. This is a refinement of Gold. Exa

Keiji Yoshida 824 Nov 18, 2022
Goview is a lightweight, minimalist and idiomatic template library based on golang html/template for building Go web application.

goview Goview is a lightweight, minimalist and idiomatic template library based on golang html/template for building Go web application. Contents Inst

foolin 310 Nov 26, 2022
A template to build dynamic web apps quickly using Go, html/template and javascript

gomodest-template A modest template to build dynamic web apps in Go, HTML and sprinkles and spots of javascript. Why ? Build dynamic websites using th

Adnaan Badr 87 Nov 23, 2022
Simple and fast template engine for Go

fasttemplate Simple and fast template engine for Go. Fasttemplate performs only a single task - it substitutes template placeholders with user-defined

Aliaksandr Valialkin 662 Dec 4, 2022
The powerful template system that Go needs

Plush Plush is the templating system that Go both needs and deserves. Powerful, flexible, and extendable, Plush is there to make writing your template

Buffalo - The Go Web Eco-System 739 Nov 27, 2022
Package damsel provides html outlining via css-selectors and common template functionality.

Damsel Markup language featuring html outlining via css-selectors, extensible via pkg html/template and others. Library This package expects to exist

Daniel Skinner 24 Oct 23, 2022
Golang Echo and html template.

golang-website-example Golang Echo and html template. move GitHub repository for hello to golang-website-example Visual Studio Code Run and Debug: lau

Ocki Bagus Pratama 0 Feb 4, 2022
Yet Another Go Project Structure Propsal

Go 项目结构实践 本仓库采用了目前社区中较为流行的 Gin, Gorm, Dig, Go-Resty 等第三方库作为使用案例,但理论上可以结合各种具有良好设计规范的工具包使用。

科学捜査官 0 Feb 6, 2022
Jet template engine

Jet Template Engine for Go Jet is a template engine developed to be easy to use, powerful, dynamic, yet secure and very fast. simple and familiar synt

null 974 Nov 30, 2022
A complete Liquid template engine in Go

Liquid Template Parser liquid is a pure Go implementation of Shopify Liquid templates. It was developed for use in the Gojekyll port of the Jekyll sta

Oliver Steele 185 Nov 21, 2022
gtpl is a template engine for glang

gtpl 使用必读 gtpl is a HTML template engine for golang gtpl 是一个 go 语言模板引擎,它能以极快的速度进行模板语法分析。相比 go 语言官方库 html/template,gtpl 的语法有着简练、灵活、易用的特点。

null 6 Nov 28, 2022
This my project template for making fiber with SSR taste by empowered mustache engine.

SSR-FIBER-TEMPLATE This my project template for making fiber with SSR taste by empowered mustache engine. Folder Hierarchy Name Description configs Co

▲ 2 May 9, 2022
Made from template temporalio/money-transfer-project-template-go

Temporal Go Project Template This is a simple project for demonstrating Temporal with the Go SDK. The full 20 minute guide is here: https://docs.tempo

MarkGorewicz 0 Jan 6, 2022
Go-project-template - Template for a golang project

This is a template repository for golang project Usage Go to github: https://git

KyberNetwork 4 Oct 25, 2022
Go-api-template - A rough template to give you a starting point for your API

Golang API Template This is only a rough template to give you a starting point f

Only Tunes Radio 3 Jan 14, 2022
Api-go-template - A simple Go API template that uses a controller-service based model to build its routes

api-go-template This is a simple Go API template that uses a controller-service

Pedro Espíndula 1 Feb 18, 2022