jet

package
v0.0.0-...-b2d0c60 Latest Latest
Warning

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

Go to latest
Published: Jan 25, 2026 License: MIT Imports: 7 Imported by: 0

README

GoHTML Jet Package

中文 | English

The jet package provides a wrapper for the Jet template engine, offering a fast and feature-rich template engine with Django/Jinja2-like syntax.

Features

  • High Performance - One of the fastest Go template engines
  • 🎨 Rich Syntax - Django/Jinja2-style template syntax
  • 🔧 Extensible - Easy to add custom functions and filters
  • 📦 embed.FS Support - Compile templates into binary for production
  • 🌐 Template Inheritance - Built-in support for template inheritance

Installation

go get github.com/h3go/gohtml
go get github.com/CloudyKit/jet/v6

Quick Start

Basic Example

Create template file templates/index.jet:

<!DOCTYPE html>
<html>
<head>
    <title>{{ Title }}</title>
</head>
<body>
    <h1>{{ Message }}</h1>
    <p>Current time: {{ now() }}</p>
</body>
</html>

Go code:

package main

import (
    "bytes"
    "fmt"
    "github.com/h3go/gohtml/jet"
)

func main() {
    // Create engine
    engine := jet.New()
    
    // Load templates from directory
    engine.JoinDir("./templates")
    
    // Render template
    var buf bytes.Buffer
    err := engine.Render(&buf, "index.jet", map[string]any{
        "Title":   "Welcome",
        "Message": "Hello, Jet!",
    })
    if err != nil {
        panic(err)
    }
    
    fmt.Println(buf.String())
}
Template Inheritance

Parent template templates/layout.jet:

<!DOCTYPE html>
<html>
<head>
    <title>{% block title %}Default Title{% endblock %}</title>
    <style>
        {% block style %}{% endblock %}
    </style>
</head>
<body>
    <header>
        <h1>My Website</h1>
    </header>
    
    <main>
        {% block content %}{% endblock %}
    </main>
    
    <footer>
        <p>&copy; 2024 My Website</p>
    </footer>
</body>
</html>

Child template templates/home.jet:

{% extends "layout.jet" %}

{% block title %}Home - My Website{% endblock %}

{% block style %}
body {
    font-family: Arial, sans-serif;
    margin: 0;
    padding: 20px;
}
{% endblock %}

{% block content %}
<h2>Welcome to Home Page</h2>
<p>User: {{ Username }}</p>
<p>Today is {{ now() }}</p>
{% endblock %}

Go code:

engine := jet.New()
engine.JoinDir("./templates")

var buf bytes.Buffer
engine.Render(&buf, "home.jet", map[string]any{
    "Username": "John",
})
Using embed.FS (Production)
package main

import (
    "embed"
    "github.com/h3go/gohtml/jet"
)

//go:embed templates/*.jet
var templateFS embed.FS

func main() {
    engine := jet.New()
    
    // Load templates from embedded filesystem
    engine.JoinFS(templateFS)
    
    var buf bytes.Buffer
    engine.Render(&buf, "index.jet", map[string]any{
        "Title": "Production",
    })
}
Development Mode

Enable development mode to disable template caching:

import "github.com/CloudyKit/jet/v6"

engine := jet.New(jet.InDevelopmentMode())
engine.JoinDir("./templates")

API Documentation

Engine
import "github.com/h3go/gohtml/jet"

// Create new engine instance
// options: Jet configuration options (e.g., jet.InDevelopmentMode())
func New(options ...jet.Option) *Engine

// Load templates from fs.FS (supports embed.FS)
func (e *Engine) JoinFS(fsys fs.FS)

// Load templates from directory
func (e *Engine) JoinDir(dir string)

// Add global variable accessible to all templates
func (e *Engine) AddGlobal(key string, value any)

// Add global function callable from all templates
func (e *Engine) AddGlobalFunc(key string, fn jet.Func)

// Render template to writer
func (e *Engine) Render(w io.Writer, name string, data map[string]any) error

Advanced Usage

Custom Global Variables
engine := jet.New()
engine.JoinDir("./templates")

// Add global variables
engine.AddGlobal("siteName", "My Website")
engine.AddGlobal("version", "1.0.0")

Use in templates:

<h1>{{ siteName }}</h1>
<p>Version: {{ version }}</p>
Custom Functions
import (
    "reflect"
    "github.com/CloudyKit/jet/v6"
    "github.com/h3go/gohtml/jet"
)

engine := jet.New()

// Add custom function
engine.AddGlobalFunc("formatPrice", func(args jet.Arguments) reflect.Value {
    price := args.Get(0).Float()
    formatted := fmt.Sprintf("$%.2f", price)
    return reflect.ValueOf(formatted)
})

engine.JoinDir("./templates")

Use in templates:

<p>Price: {{ formatPrice(99.99) }}</p>

Jet Template Syntax

Variables
{{ variable }}
{{ object.field }}
{{ array[0] }}
Control Structures
{% if condition %}
    ...
{% else if otherCondition %}
    ...
{% else %}
    ...
{% endif %}

{% for item in items %}
    {{ item }}
{% endfor %}

{% for key, value in map %}
    {{ key }}: {{ value }}
{% endfor %}
Filters
{{ text | upper }}
{{ text | lower }}
{{ text | trim }}
{{ number | int }}
{{ number | float }}
Comments
{* This is a comment *}

Performance Optimization

Production Best Practices
  1. Use embed.FS: Compile templates into binary
  2. Disable Development Mode: Don't use jet.InDevelopmentMode() in production
  3. Template Caching: Jet automatically caches compiled templates
package main

import (
    "embed"
    "github.com/h3go/gohtml/jet"
)

//go:embed templates/*.jet
var templateFS embed.FS

func newEngine() *jet.Engine {
    engine := jet.New() // Production mode (caching enabled)
    engine.JoinFS(templateFS)
    return engine
}
Development Hot Reload
import "github.com/CloudyKit/jet/v6"

func newEngine() *jet.Engine {
    engine := jet.New(jet.InDevelopmentMode()) // Disable caching
    engine.JoinDir("./templates")
    return engine
}

Resources

License

MIT License - See LICENSE

Documentation

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

This section is empty.

Types

type Engine

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

Engine 是 Jet 模板引擎的封装 Jet 是一个快速且功能丰富的模板引擎,语法类似 Django/Jinja2

func New

func New(options ...jet.Option) *Engine

New 创建一个新的 Jet Engine 实例 options 是 Jet 的配置选项,例如:

  • jet.InDevelopmentMode() - 开发模式,禁用缓存
  • jet.WithSafeWriter(nil) - 自定义安全写入器

示例:

engine := jet.New(jet.InDevelopmentMode())

func (*Engine) AddGlobal

func (e *Engine) AddGlobal(key string, value any)

AddGlobal 添加全局变量,所有模板都可以访问 key 是变量名,value 是变量值

示例:

engine.AddGlobal("siteName", "My Website")
engine.AddGlobal("version", "1.0.0")

func (*Engine) AddGlobalFunc

func (e *Engine) AddGlobalFunc(key string, fn jet.Func)

AddGlobalFunc 添加全局函数,所有模板都可以调用 key 是函数名,fn 是函数实现

示例:

engine.AddGlobalFunc("formatPrice", func(args jet.Arguments) reflect.Value {
    price := args.Get(0).Float()
    return reflect.ValueOf(fmt.Sprintf("$%.2f", price))
})

func (*Engine) JoinDir

func (e *Engine) JoinDir(dir string)

JoinDir 从指定目录加载模板 dir 是目录的绝对路径或相对路径

示例:

engine := jet.New()
engine.JoinDir("./templates")

func (*Engine) JoinFS

func (e *Engine) JoinFS(fsys fs.FS)

JoinFS 从 fs.FS 文件系统加载模板 fsys 可以是 embed.FS、os.DirFS 或任何实现了 fs.FS 接口的类型

示例:

//go:embed templates/*.jet
var templateFS embed.FS

engine := jet.New()
engine.JoinFS(templateFS)

func (*Engine) Render

func (e *Engine) Render(w io.Writer, name string, data map[string]any) error

Render 渲染指定的模板 w 是输出目标,name 是模板名称,data 是传递给模板的数据

返回的错误类型:

  • gohtml.ErrNotFound - 模板文件不存在
  • gohtml.ErrSyntax - 模板语法错误
  • 其他错误 - 模板执行时的运行时错误

示例:

err := engine.Render(w, "index.jet", map[string]any{
    "Title": "Welcome",
    "User":  user,
})

type Loader

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

Loader 实现了 Jet 的模板加载器接口 支持从多个 fs.FS 文件系统中加载模板,按照添加顺序依次查找 这允许模板覆盖:后添加的文件系统中的模板会优先于先添加的

func (*Loader) Exists

func (l *Loader) Exists(name string) bool

Exists 检查指定名称的模板是否存在 实现了 jet.Loader 接口的 Exists 方法

查找策略:

  1. 规范化模板名称(移除前导斜杠)
  2. 按照文件系统添加顺序依次查找
  3. 忽略所有错误,继续查找下一个文件系统
  4. 只有非目录文件才被认为是存在的模板

返回 true 如果找到模板文件,否则返回 false

func (*Loader) Join

func (l *Loader) Join(f fs.FS)

Join 添加一个文件系统到加载器 文件系统按添加顺序存储,查找模板时会按顺序遍历 可以多次调用以支持多个模板目录或嵌入的文件系统

示例:

loader := &Loader{}
loader.Join(os.DirFS("./templates"))
loader.Join(embeddedFS)

func (*Loader) Open

func (l *Loader) Open(name string) (io.ReadCloser, error)

Open 打开指定名称的模板文件 实现了 jet.Loader 接口的 Open 方法

查找策略:

  1. 规范化模板名称(移除前导斜杠)
  2. 按照文件系统添加顺序依次查找
  3. 跳过不存在的文件和目录
  4. 返回第一个找到的非目录文件

返回 fs.ErrNotExist 如果在所有文件系统中都找不到模板

Jump to

Keyboard shortcuts

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