MCPcopy
hub / github.com/flosch/pongo2

github.com/flosch/pongo2 @v6.1.0 sqlite

repository ↗ · DeepWiki ↗ · release v6.1.0 ↗
462 symbols 1,472 edges 51 files 112 documented · 24%
README

pongo2

PkgGoDev Build Status Run on Repl.it

pongo2 is a Django-syntax like templating-language (official website).

Install/update using go get (no dependencies required by pongo2):

go get -u github.com/flosch/pongo2/v6

Please use the issue tracker if you're encountering any problems with pongo2 or if you need help with implementing tags or filters (create a ticket!).

First impression of a template

<html>
  <head>
    <title>Our admins and users</title>
  </head>
  {# This is a short example to give you a quick overview of pongo2's syntax. #}
  {% macro user_details(user, is_admin=false) %}




    <h2 {% if (user.karma>= 40) || (user.karma > calc_avg_karma(userlist)+5) %} class="karma-good"{% endif %}>


      {{ user }}
    </h2>




This user registered {{ user.register_date|naturaltime }}.






The user's biography:





      {{ user.biography|markdown|truncatewords_html:15 }}
      <a href="https://github.com/flosch/pongo2/raw/v6.1.0/user/{{ user.id }}/">read more</a>




    {% if is_admin %}


This user is an admin!


    {% endif %}



  {% endmacro %}

  <body>


    <h1>Our admins</h1>
    {% for admin in adminlist %} {{ user_details(admin, true) }} {% endfor %}

    <h1>Our members</h1>
    {% for user in userlist %} {{ user_details(user) }} {% endfor %}
  </body>
</html>

Features

Security

Template loaders do not clamp to a base directory

LocalFilesystemLoader (and the Default* set built on it) treats the baseDir as a hint, not a jail. Absolute paths are honored verbatim and relative paths containing .. are joined without normalization, so any filename that reaches a loader can read outside the configured directory. This affects every code path that resolves a filename — FromFile, {% include %}, {% extends %}, {% import %}, {% ssi %} — including the variants that take a runtime expression (e.g. {% include user_chosen_template %}).

HttpFilesystemLoader and FSLoader likewise pass the resolved name straight to the underlying filesystem; whether .. is rejected depends entirely on that filesystem (http.Dir does, many in-memory fs.FS implementations do not).

Treat template filenames as trusted input. If your application cannot guarantee that, validate the filename before handing it to pongo2, or wrap the loader with a custom TemplateLoader.Abs that rejects absolute paths and .. segments.

Caveats

Filters

  • date / time: The date and time filter are taking the Golang specific time- and date-format (not Django's one) currently. Take a look on the format here.
  • stringformat: stringformat does not take Python's string format syntax as a parameter, instead it takes Go's. Essentially {{ 3.14|stringformat:"pi is %.2f" }} is fmt.Sprintf("pi is %.2f", 3.14).
  • escape / force_escape: Unlike Django's behaviour, the escape-filter is applied immediately. Therefore there is no need for a force_escape-filter yet.

Tags

  • for: All the forloop fields (like forloop.counter) are written with a capital letter at the beginning. For example, the counter can be accessed by forloop.Counter and the parentloop by forloop.Parentloop.
  • now: takes Go's time format (see date and time-filter).

Misc

  • not in-operator: You can check whether a map/struct/string contains a key/field/substring by using the in-operator (or the negation of it): {% if key in map %}Key is in map{% else %}Key not in map{% endif %} or {% if !(key in map) %}Key is NOT in map{% else %}Key is in map{% endif %}.

Add-ons, libraries and helpers

Official

  • pongo2-addons - Official additional filters/tags for pongo2 (for example a markdown-filter). They are in their own repository because they're relying on 3rd-party-libraries.

3rd-party

Please add your project to this list and send me a pull request when you've developed something nice for pongo2.

Who's using pongo2

I'm compiling a list of pongo2 users. Add your project or company!

API-usage examples

Please see the documentation for a full list of provided API methods.

A tiny example (template string)

// Compile the template first (i. e. creating the AST)
tpl, err := pongo2.FromString("Hello {{ name|capfirst }}!")
if err != nil {
    panic(err)
}
// Now you can render the template with the given
// pongo2.Context how often you want to.
out, err := tpl.Execute(pongo2.Context{"name": "florian"})
if err != nil {
    panic(err)
}
fmt.Println(out) // Output: Hello Florian!

Example server-usage (template file)

package main

import (
    "github.com/flosch/pongo2/v6"
    "net/http"
)

// Pre-compiling the templates at application startup using the
// little Must()-helper function (Must() will panic if FromFile()
// or FromString() will return with an error - that's it).
// It's faster to pre-compile it anywhere at startup and only
// execute the template later.
var tplExample = pongo2.Must(pongo2.FromFile("example.html"))

func examplePage(w http.ResponseWriter, r *http.Request) {
    // Execute the template per HTTP request
    err := tplExample.ExecuteWriter(pongo2.Context{"query": r.FormValue("query")}, w)
    if err != nil {
        http.Error(w, err.Error(), http.StatusInternalServerError)
    }
}

func main() {
    http.HandleFunc("/", examplePage)
    http.ListenAndServe(":8080", nil)
}

Extension points exported contracts — how you extend this code

INode (Interface)
(no doc) [42 implementers]
parser.go
TemplateLoader (Interface)
TemplateLoader allows to implement a virtual file system. [3 implementers]
template_sets.go
TagParser (FuncType)
This is the function signature of the tag's parser you will have to implement in order to create a new tag. 'doc' is pr
tags.go
FilterFunction (FuncType)
FilterFunction is the type filter functions must fulfil
filters.go
TemplateWriter (Interface)
(no doc) [1 implementers]
template.go
IEvaluator (Interface)
(no doc) [11 implementers]
parser.go
INodeTag (Interface)
(no doc)
tags.go

Core symbols most depended-on inside this repo

AsValue
called by 125
value.go
Error
called by 110
error.go
String
called by 91
value.go
getResolvedValue
called by 81
value.go
WriteString
called by 54
template.go
Integer
called by 53
value.go
RegisterFilter
called by 51
filters.go
Execute
called by 41
parser.go

Shape

Method 221
Function 160
Struct 66
Interface 6
TypeAlias 6
FuncType 3

Languages

Go100%

Modules by API surface

filters_builtin.go53 symbols
variable.go43 symbols
value.go35 symbols
pongo2_template_test.go34 symbols
parser_expression.go31 symbols
parser.go26 symbols
template_sets.go22 symbols
lexer.go22 symbols
template.go17 symbols
template_loader.go15 symbols
filters.go10 symbols
context.go10 symbols

Dependencies from manifests, versioned

github.com/kr/prettyv0.2.1 · 1×
github.com/kr/textv0.1.0 · 1×
gopkg.in/check.v1v1.0.0-2020113013444 · 1×

For agents

$ claude mcp add pongo2 \
  -- python -m otcore.mcp_server <graph>

⬇ download graph artifact