gledki

package module
v0.7.1 Latest Latest
Warning

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

Go to latest
Published: Feb 28, 2024 License: MIT Imports: 12 Imported by: 1

README

Gledki (Гледки)

Package gledki provides a templates and data manager for fasttemplate

Because fasttemplate is minimalisitic, the need for this wrapper arose. Two template directives were implemented – wrapper and include. They make gledki powerful enough for use in big and complex web applications.

The main template (the one which partial path you pass as argument to Gledki.Execute(...)) can be compiled from several files – as many as you need – with the simple approach of wrapping and including partial files recursively. TagFunc(...) allows us to keep logic into our Go code and prepare pieces of the output as needed. Leveraging cleverly TagFunc gives us complete separation of concerns. This simple but powerful technic made me write this wrapper. Ah, and „gledki(гледки)“ means "views" in Bulgarian.

See the tests and sample templates for usage examples.

Note!

This is my first module in Go, so I would be glad to get advices for improvements, exspecially for idiomatic Go.

Example usage


import (
	"fmt"
	"io"
	"os"

	gl "github.com/kberov/gledki"
	"github.com/labstack/gommon/log"
)

// Multiple templates paths. The first found template with a certain name is
// loaded. Convenient for themes, multidomain sites etc.
var templatesRoots = []string{"./testdata/tpls/theme","./testdata/tpls" }
var filesExt = ".htm"

//...

// Once on startup.
tpls, err := gl.New(templatesRoots, filesExt, [2]string{"<%", "%>"}, false)
if err != nil {
	fmt.Print("Error:", err.Error())
	os.Exit(1)
}
tpls.Logger.SetLevel(log.DEBUG)
// …
// Later… many times and with various data (string, []byte, gledki.TagFunc)
tpls.Stash = map[string]any{"generator": "Гледки"}

// Somwhere else in your program…
tpls.MergeStash(gl.Stash{
	"title": "Hello",
	"body": gl.TagFunc(func(w io.Writer, tag string) (int, error) {
		// tmpls.Stash entries and even the entire Stash can be modified
		// from within tmpls.TagFunc
		tpls.Stash["generator"] = "Something"
		return w.Write([]byte("<p>Some complex callculations to construct the body.</p>"))
	}),
})

// Even later…
// See used templates in testdata/tpls.
tpls.Execute(os.Stdout, "simple")
// Output:
// <!doctype html>
// <html>
//     <head>
//         <meta charset="UTF-8">
//         <meta name="generator" content="Гледки">
//         <title>Hello</title>
//     </head>
//     <body>
//         <header><h1>Hello</h1></header>
//         <h1>Hello</h1>
//         <section>
//             <p>Some complex callculations to construct the body.</p>
//             <p>Changed generator to "Something".</p>
//         </section>
//         <footer>Тази страница бе създадена с Something.</footer>
//     </body>
// </html>

See other examples in gledki_test.go.

Documentation

Overview

Package gledki provides a templates and data manager for fasttemplate.

Because fasttemplate is minimalisitic, the need for this wrapper arose. Two template directives were implemented – `wrapper` and `include`. They make gledki powerful enough for use in big and complex web applications.

The main template (the one which partial path you pass as argument to Gledki.Execute) can be compiled from several files – as many as you need – with the simple approach of wrapping and including partial files recursively. TagFunc allows us to keep logic into our Go code and prepare pieces of the output as needed. Leveraging cleverly TagFunc gives us complete separation of concerns. In TagFunc we can invoke Gledki.Compile to preprare partial templates, make any calculatuons and prepare the output for replacement in the main template. No need to learn a new template language. The possibilities of his simple but powerful technique ispired me to write this wrapper. Ah, and „gledki(гледки)“ means "views" in Bulgarian.

See the tests and sample templates for usage examples.

Index

Examples

Constants

This section is empty.

Variables

View Source
var CacheTemplates bool = true

CacheTemplates can be set to false to disable caching of compiled templates both in memory and on disk during development.

View Source
var CompiledSuffix = "c"

CompiledSuffix is appended to the extension of compiled templates.

Functions

This section is empty.

Types

type Gledki

type Gledki struct {
	// A map for replacement into templates
	Stash Stash

	// File extension of the templates, for example: ".htm".
	Ext string
	// Root folders, where template files reside, for example
	// ["./templates","example.com","themeX"]. They will be wallked up in the
	// order they are provided to find the template file, passed to
	// [Gledki.Execute]. The first found is used.
	Roots []string
	// Pair of Tags, for example:  "${", "}".
	Tags [2]string
	// How deeply files can be included into each other.
	// Default: 3 starting from 0 in the main template.
	IncludeLimit int

	// Any logger defining Debug, Error, Info, Warn... See tmpls.Logger.
	Logger
	// contains filtered or unexported fields
}

Gledki manages files and data for fasttemplate.

func Must added in v0.6.0

func Must(roots []string, ext string, tags [2]string, loadFiles bool) *Gledki

Must is a convenient wrapper for New, which returns only &Gledki or panics in case of any error.

func New

func New(roots []string, ext string, tags [2]string, loadFiles bool) (*Gledki, error)

New instantiates a new Gledki struct and returns a reference to it. Prepares Stash and loads all template files from disk under the given `roots` if `loadFiles` is true. Otherwise postpones the loading of the needed file until Gledki.Compile is invoked automatically in Gledki.Execute.

func (*Gledki) Compile

func (t *Gledki) Compile(path string) (string, error)

Compile composes a template and returns its content or an error. This means:

  • The file is loaded from disk using Gledki.LoadFile for use by Gledki.Execute.
  • if the template contains `${wrapper some/file}`, the wrapper file is wrapped around it. Only one `wrapper` directive is allowed per file.
  • if the template contains any `${include some/file}` the files are loaded, wrapped (if there is a wrapper directive in them) and included at these places without rendering any placeholders. The inclusion is done recursively. See Gledki.IncludeLimit.
  • The compiled template is stored in a private map[filename(string)]string, attached to *Gledki for subsequent use during the same run of the application. The content of the compiled template is stored on disk with a suffix (see CompiledSuffix), attached to the extension of the file in the same directory where the template file resides. The storing of the compiled file is done concurently in a goroutine while being executed.
  • On the next run of the application the compiled file is simply loaded and its content retuned. All the steps above are skipped.

Panics in case the *Gledki.IncludeLimit is reached. If you have deeply nested included files you may need to set a bigger integer. This method is suitable for use in a ft.TagFunc to preprare parts of the output to be replaced in the main template.

func (*Gledki) Execute

func (t *Gledki) Execute(w io.Writer, path string) (int64, error)

Execute compiles (if needed) and executes the passed template using fasttemplate.Execute. The path is resolved by prefixing the root folder and attaching the extension, passed to New, if the passed file is only a base name. Example: `path := "view"` => `/home/user/app/templates/view.htm`.

Example (Simple)
package main

import (
	"fmt"
	"io"
	"os"

	gl "github.com/kberov/gledki"
	"github.com/labstack/gommon/log"
)

var Roots = []string{"testdata/tpls"}
var filesExt = ".htm"

func main() {

	// Once on startup.
	tpls, err := gl.New(Roots, filesExt, [2]string{"<%", "%>"}, false)
	if err != nil {
		fmt.Print("Error:", err.Error())
		os.Exit(1)
	}
	tpls.Logger.SetLevel(log.DEBUG)
	// …
	// Later… many times and with various data (string, []byte, gledki.TagFunc)
	tpls.Stash = map[string]any{"generator": "Гледки"}

	// Somwhere else in your program…
	tpls.MergeStash(gl.Stash{
		"title": "Hello",
		"body": gl.TagFunc(func(w io.Writer, tag string) (int, error) {
			// tmpls.Stash entries and even the entire Stash can be modified
			// from within tmpls.TagFunc
			tpls.Stash["generator"] = "Something"
			return w.Write([]byte("<p>Some complex callculations to construct the body.</p>"))
		}),
	})

	// Even later…
	// See used templates in testdata/tpls.
	tpls.Execute(os.Stdout, "simple")
}
Output:

<!doctype html>
<html>
    <head>
        <meta charset="UTF-8">
        <meta name="generator" content="Гледки">
        <title>Hello</title>
    </head>
    <body>
        <header><h1>Hello</h1></header>
        <h1>Hello</h1>
        <section>
            <p>Some complex callculations to construct the body.</p>
            <p>Changed generator to "Something".</p>
        </section>
        <footer>Тази страница бе създадена с Something.</footer>
    </body>
</html>

func (*Gledki) FtExecStd

func (t *Gledki) FtExecStd(tmpl string, w io.Writer, data Stash) (int64, error)

FtExecStd is a wrapper around fasttemplate.ExecuteStd. Useful for preparing partial templates which will be later included in the main template, because it keeps unknown placeholders untouched.

func (*Gledki) FtExecString added in v0.7.0

func (t *Gledki) FtExecString(template string, data Stash) string

FtExecString is a wrapper for fasttemplate.ExecuteString. Useful for preparing partial templates which will be later included in the main template. It does not keep unknown tags.

func (*Gledki) FtExecStringStd

func (t *Gledki) FtExecStringStd(template string, data Stash) string

FtExecStringStd is a wrapper for fasttemplate.ExecuteStringStd. Useful for preparing partial templates which will be later included in the main template, because it keeps unknown placeholders untouched. It can be used as a drop-in replacement for strings.Replacer

func (*Gledki) LoadFile

func (t *Gledki) LoadFile(path string) (string, error)

LoadFile is used to load a template from disk or from cache, if already loaded before. Returns the template text or error if template cannot be loaded.

func (*Gledki) MergeStash

func (t *Gledki) MergeStash(data Stash)

MergeStash adds entries into the Stash, used by fasttemplate.Execute in Gledki.Execute. If entries with the same key exist, they will be overriden with the new values.

func (*Gledki) MustLoadFile added in v0.6.0

func (t *Gledki) MustLoadFile(path string) string

MustLoadFile does the same as Gledki.LoadFile, but panics in case the template file cannot be loaded.

type Logger

type Logger interface {
	Debug(args ...any)
	Debugf(format string, args ...any)
	DisableColor()
	Error(args ...any)
	Errorf(format string, args ...any)
	Fatal(i ...any)
	Fatalf(format string, args ...any)
	Info(args ...any)
	Infof(format string, args ...any)
	Panic(i ...any)
	Panicf(format string, args ...any)
	SetHeader(h string)
	SetLevel(v log.Lvl)
	SetOutput(w io.Writer)
	Warn(args ...any)
	Warnf(format string, args ...any)
}

Logger is implemented by gommon/log on which we depend.

type Stash

type Stash map[string]any

Stash is `map[string]any` for replacement into templates. It has the value types' requirements for fasttemplate:

  • []byte - the fastest value type
  • string - convenient value type
  • TagFunc - flexible value type

type TagFunc

type TagFunc = fasttemplate.TagFunc

TagFunc is an alias for fasttemplate.TagFunc.

Jump to

Keyboard shortcuts

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