feelers

package
v0.20.0 Latest Latest
Warning

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

Go to latest
Published: Oct 26, 2026 License: AGPL-3.0 Imports: 4 Imported by: 0

Documentation

Overview

Package feelers renders the template language Atlas's forms already speak.

form-js's Text and HTML views evaluate their content with feelers (bpmn-io/feelers 3.1.0, bundled in api/web/vendor/form-js): text with {{ FEEL }} placeholders, {{#if FEEL}}…{{/if}} and {{#loop FEEL}}…{{/loop}} sections. A mail text is written in the same language (ADR-0487) and is rendered on the server, so this package implements it in Go: parsed, and every FEEL block compiled, once when the model is deployed (I5); rendered when the mail is sent.

It follows feelers wherever feelers decides, so a template reads the same in a form and in a mail:

  • a placeholder renders FEEL's string() of its value, and null as nothing;
  • {{#if}} renders its section when the value is truthy as JavaScript has it — false, null, 0 and "" are not, everything else is, an empty list included;
  • {{#loop}} renders its section once per list element, not at all for null and once for any other single value. Inside, the element's fields are names of their own, `this` is the element and `parent` the enclosing context; the variables outside the loop are reached through `parent`, as in feelers;
  • an opening tag swallows the line break directly after it, and so does a closing tag, which puts one back after a rendered section that did not end with one. That is what lets a section's tags stand on lines of their own.

Where feelers is lenient because a form must show whatever it is given, this package is strict when it compiles: an unclosed {{, a section without its end, an end without its section and FEEL that does not compile are refused when the model is deployed, rather than rendered as a warning sign in a mail that has already gone out. When it renders it is as lenient as the rest of Atlas's FEEL: a placeholder whose expression fails renders as nothing, and is reported.

A leading '=' is not this package's business. In Atlas it makes a whole value one FEEL expression, which the caller decides before it considers a template.

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

func IsTemplate

func IsTemplate(src string) bool

IsTemplate reports whether src uses the template language at all — whether it has a {{ in it. A value without one is plain text and needs no template.

Types

type CompileFunc

type CompileFunc func(src string) (*expr.Compiled, error)

CompileFunc compiles one FEEL block. The compiler hands in its deploy gate, so the FEEL in a template is held to the rules every other FEEL in a model is (ADR-0388).

type Error

type Error struct {
	Line, Column int
	Msg          string
	Err          error
}

Error is a template that does not parse, or whose FEEL does not compile, with the place of the tag at fault: Line and Column count from 1, the column in characters.

func (*Error) Error

func (e *Error) Error() string

func (*Error) Unwrap

func (e *Error) Unwrap() error

type Problem

type Problem struct {
	Expression string `json:"expression"`
	Message    string `json:"message"`
}

Problem is a placeholder or section that rendered as nothing: its expression failed, or answered null where a value was wanted. A mail goes out regardless, as one with a failed FEEL field always has; a preview shows the problems beside the result.

type Scope

type Scope interface {
	// Lookup answers a variable's value, and whether it is set.
	Lookup(name string) (expr.Value, bool)
	// Names lists every variable. It is read only for `this` at the top level, which
	// names the whole scope as one context, as it does in feelers.
	Names() []string
}

Scope is what a template's names resolve against at its top level: the variables the task sees.

type Template

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

Template is a parsed template with its FEEL compiled. It is immutable and safe for concurrent rendering, like the compiled process that holds it.

func Compile

func Compile(src string, compile CompileFunc) (*Template, error)

Compile parses src and compiles each of its FEEL blocks with compile.

func (*Template) Render

func (t *Template) Render(scope Scope, escape func(string) string) (string, []Problem)

Render renders the template against scope. escape, when set, is applied to every value a placeholder inserts and never to the template's own text — an HTML body passes one, so a variable cannot add markup to it. Render does not fail: whatever cannot be evaluated renders as nothing and is listed in the problems.

func (*Template) Source

func (t *Template) Source() string

Source returns the template as it was written.

type Vars

type Vars map[string]expr.Value

Vars is a Scope over FEEL values already in hand.

func (Vars) Lookup

func (v Vars) Lookup(name string) (expr.Value, bool)

Lookup implements Scope.

func (Vars) Names

func (v Vars) Names() []string

Names implements Scope.

Jump to

Keyboard shortcuts

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