fet

package module
v1.2.3 Latest Latest
Warning

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

Go to latest
Published: Feb 1, 2024 License: MIT Imports: 3 Imported by: 0

README

FET

tag test codecov

FET is a golang template engine that can tranlate smarty like template code into golang html/template.

Why FET

FET means Friendly, Easily for Template code. The official golang package html/template is a fully functional template engine, but it has a few defects with user experience, so you need FET.

Features
  • Expression logics
  • Use incldue with defined variables scopes
  • Use extends inherit base template with defined variables scopes
  • Limited support for for and capture

Document

Document

中文文档

Usage

it's more likely to the php template engine smarty.

  • inherit

    {%extends "base.html"%}
    
  • blocks for inherit

    {%block "header"%}
      <div>some code here</div>
    {%/block%}
    
  • include

    {%include file="header.html" var=1%}
    
  • loop, do not support keyword break continue

    // for Gofet mode
    {%for item,key in list%}
      // output
    {%/for%}
    
    {%for i = 0, j = 10; i < j; i++%}
      // output
    {%/for%}
    // for Smarty mode
    {%foreach $list as $key => $item%}
      // output
    {%/foreach%}
    // for
    {%for $i = 0, $j = 10; $i < $j; $i++%}
      // output
    {%/for%}
    
  • if condition

    {%if $num > 100%}
    
    {%elseif $num < 50%}
    
    {%else%}
    
    {%/if%}
    
  • output

    {%$item.url%}
    
  • pipe funcs

    {%$item.title|truncate:30%}
    
  • variable define

    {%$title = "this is a title"%}
    
  • capture

    {%capture "hello"%}hello{%/capture%}
    {%if true%}
      {%$fet.capture.hello%},wolrd!
    {%else%}
      just {%$fet.capture.hello%}!
    {%/if%}
    
  • static variables

    {%$fet.capture.xxx%}
    {%$fet.config.leftDelimiter%}
    {%$fet.config.rightDelimiter%}
    {%$fet.config.templateDir%}
    {%$fet.config.compileDir%}
    {%$fet.now%}
    {%$fet.debug%} // will output all the variables that assigned in the template<include variables that difined in the template by yourself> to the js devtools's Console panel.
    
  • special variables

    {%$ROOT%}  // will output $
    {%$fet%} // will output .
    
Expression
  1. operators: You can either use the keyword operator or the punctuation.

    keyword punctuation example
    and && 1 && 2 <=> 1 and 2
    or || 1 || 2 <=> 1 or 2
    not ! !a <=> not a
    eq == a == b <=> a eq b
    ne != a != b <=> a ne b
    gt > a > b <=> a gt b
    ge >= a >= b <=> a ge b
    lt < a < b <=> a lt b
    le <= a <= b <=> a le b
    bitor - a bitor b
    - & a & b
    - ^ a ^ b
    - + a + b
    - - a - b
    - * a * b
    - / a / b
    - % a % b
    - ** a ** b

    Be careful of the and and or operators, they don't have short circuit with conditions.

  2. pipe
    | pipeline funcs
    : set parameters for pipeline funcs

  3. numbers
    hex: 0xffff
    octal: 0o777
    binary: 0b1000
    scientific notation 1e10

String concat
{% $sayHello = "world" %}
{% "hello `$sayHello`"%} // output "hello world"

use `` for variable or expression in strings. do not use +.

Func Maps
  • Math
    min max floor ceil

  • Formats
    number_format

  • Strings truncate concat ucwords

  • Assert
    empty

  • Length
    count

  • Output
    safe

  • view more in funcs.go

Config types.Mode
  • types.Smarty
    the variable and field must begin with $, use foreach tag for loops.
  • types.Gofet
    the variable and field mustn't begin with $, use for tag for loops.
In development
# install command line tool `fetc`
go get -v github.com/fefit/fetc
# then init the config, will make a config file `fet.config.json`
fetc init
# then watch the file change, compile your fet template file immediately
fetc watch
Demo code
package main

import (
  "os"
  "github.com/fefit/fet"
  "github.com/fefit/fet/types"
)

func main(){
  conf := &fet.Config{
    LeftDelimiter: "{%", // default "{%"
    RightDelimiter: "%}", // default "%}"
    TemplateDir: "tmpls", //  default "templates"
    CompileDir: "views", // default "templates_c",
    Ignores: []string{"inc/*"}, // ignore compile,paths and files that will be included and extended. use filepath.Match() method.
    UcaseField: false, // default false, if true will auto uppercase field name to uppercase.
    CompileOnline: false, // default false, you should compile your template files offline
    Glob: false, // default false, if true, will add {{define "xxx"}}{{end}} to wrap the compiled content,"xxx" is the relative pathname base on your templateDir, without the file extname.
    AutoRoot: false, // default false,if true, if the variable is not assign in the scope, will treat it as the root field of template data, otherwise you need use '$ROOT' to index the data field.
    Mode: types.Smarty, // default types.Smarty, also can be "types.Gofet"
  }
  fet, _ := fet.New(conf)
  // assign data
  data := map[string]interface{}{
    "Hello": "World"
  }
  // the index.html {%$ROOT.Hello%}
  // Display
  fet.Display("index.html", data, os.Stdout)
  // will output: World
}

API
static methods
  • fet.LoadConf(configFile string) (*types.FetConfig, error)

    if you use the command line fetc build a config file fet.config.json, then you can use fet.LoadConf to get the config.

  • fet.New(config *types.FetConfig) (instance *Fet, error)

    get a fet instance.

instance methods
  • instance.Compile(tpl string, createFile bool) (result string, err error)

    compile a template file, if createFile is true, will create the compiled file.

  • instance.CompileAll() error

    compile all files need to compile.

  • instance.Display(tpl string, data interface{}, output io.Wirter) error

    render the parsed html code into output.

  • instance.Fetch(tpl string, data interface{}) (result string, err error)

    just get the parsed string code, it always use CompileOnline mode.

Use in project

  1. compile mode

    just use fet compile your template files offline, and add the FuncMap lib/funcs/funcs.go to your project.

  2. install mode

    install fet,and use fet.Display(tpl, data, io.Writer) to render the template file.

License

MIT License.

Documentation

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

func NewEngine

func NewEngine()

Types

type Assignment

type Assignment struct {
	Scope InScope
	Name  lexer.IToken
	Value *lexer.Expression
}

*

  • Assignment

type Block

type Block struct {
	NameEnded bool
	Meta      *RegisterBlock
	Node      *LinkedNode
	End       *BytesMatcher
}

func (*Block) Add

func (block *Block) Add(bt byte, parser *Parser) (ICode, error)

func (*Block) AddEnd

func (block *Block) AddEnd(bt byte, parser *Parser) (ICode, error)

func (*Block) Type

func (_ *Block) Type() CodeType

type BlockEnd

type BlockEnd struct {
	Name  *Bytes
	Index uint
}

func (*BlockEnd) Add

func (blockEnd *BlockEnd) Add(bt byte, parser *Parser) (ICode, error)

func (*BlockEnd) Type

func (blockEnd *BlockEnd) Type() CodeType

type BlockFeature

type BlockFeature struct {
	Meta *RegisterBlockFeature
	Name Bytes
}

type BuiltInPropParser

type BuiltInPropParser struct {
	Props []Property
}

*

  • built-in property parser

type Bytes

type Bytes = []byte

type BytesMatcher

type BytesMatcher struct {
	IsEnd      bool
	Index      int
	SpaceIndex int
	Raw        *Bytes
}

func (*BytesMatcher) Match

func (matcher *BytesMatcher) Match(bt byte) (bool, error)

type CodeType

type CodeType = uint
const (
	BlockCode CodeType = iota
	BlockFeatureCode
	BlockEndCode
	UnkownCode
	DetectCode
	CommentCode
	RawHtmlCode
	OutputCode
	AssignCode
)

type Comment

type Comment struct {
	Raw Bytes
}

*

*

func (*Comment) Add

func (comment *Comment) Add(bt byte, parser *Parser) (ICode, error)

func (*Comment) Type

func (_ *Comment) Type() CodeType

type Config

type Config struct {
	LeftDelimiter  Bytes
	RightDelimiter Bytes
	CommentSymbol  byte
	RegisterBlocks []*RegisterBlock
}

type Context

type Context struct {
	Scope Bytes // scope

}

type Detect

type Detect struct {
	Parsed      Bytes
	ProxyHandle *func(bt byte, parser *Parser) (ICode, error)
	Code        ICode
	EndMatched  int
	MaybeBlocks []*RegisterBlockFeature
}

*

*

func (*Detect) Add

func (detect *Detect) Add(bt byte, parser *Parser) (ICode, error)

func (*Detect) HandleBlock

func (detect *Detect) HandleBlock(bt byte, parser *Parser) (ICode, error)

func (*Detect) HandleMaybeBlockOrBlockFeature

func (detect *Detect) HandleMaybeBlockOrBlockFeature(bt byte, parser *Parser) (ICode, error)

func (*Detect) HandleMaybeOutputOrAssign

func (detect *Detect) HandleMaybeOutputOrAssign(bt byte, parser *Parser) (ICode, error)

func (*Detect) HandleOutput

func (detect *Detect) HandleOutput(bt byte, parser *Parser) (ICode, error)

func (*Detect) Type

func (_ *Detect) Type() CodeType

type Engine

type Engine interface {
	Config(config Config)
}

type Extend

type Extend struct {
	Tpl     *Template
	TplPath *TplPath
}

*

  • Extend

type Fet

type Fet struct {
}

type ICode

type ICode interface {
	Add(bt byte, parser *Parser) (ICode, error)
	Type() CodeType
}

type IParser

type IParser interface {
	// if the parser allowed clear
	Clear() bool
}

type InScope

type InScope = uint
const (
	LocalScope InScope = iota
	ParentScope
	GlobalScope
)

type Include

type Include struct {
	Depth uint
	Node  *LinkedNode
	Tpl   *Template
}

*

  • Include

type LinkedNode

type LinkedNode struct {
	Parent     ICode // parent node
	Prev       ICode // prev node
	Next       ICode // next node
	FirstChild ICode // first child
}

type Output

type Output struct {
	Exp  *lexer.Expression
	Node *LinkedNode
}

*

  • Output

type Parser

type Parser struct {
	Config   *Config  // config
	CurCode  ICode    // current code
	CurBlock *Block   // current block
	Blocks   []*Block // block chains
}

*

*

func (*Parser) MatchBlock

func (parser *Parser) MatchBlock(name []byte) *RegisterBlock

func (*Parser) Parse

func (parser *Parser) Parse(bt byte) error

type PathType

type PathType = uint
const (
	AbsPath  PathType = iota // absolute path
	RelaPath                 // relative path
	BasePath                 // path base on
)

type Property

type Property struct {
	Shorthand      bool
	Required       bool
	Prop           string
	ValueValidator func(token lexer.IToken) error
}

type RawHtml

type RawHtml struct {
	Raw  Bytes
	Node *LinkedNode
}

*

  • Raw Html

func (*RawHtml) Add

func (rawHtml *RawHtml) Add(bt byte, parser *Parser) (ICode, error)

func (*RawHtml) Type

func (_ *RawHtml) Type() CodeType

type RegisterBlock

type RegisterBlock struct {
	Name     Bytes
	Features []RegisterBlockFeature
	Parser   IParser
}

*

*

type RegisterBlockFeature

type RegisterBlockFeature struct {
	Once       bool  // only allowed appear once
	Last       bool  // only allowed appear at last feature
	SpaceIndex int   // if allow whitespace in keywords e.g. else if => elseif
	Name       Bytes // feature block name
	Parser     IParser
}

type Slot

type Slot struct {
	Name  Bytes
	Node  *LinkedNode
	Codes []ICode
}

*

  • Slot

type Template

type Template struct {
	TplPath *TplPath
	Codes   []ICode
}

*

  • Template

type TplPath

type TplPath struct {
	Type    PathType
	Path    []Bytes
	AbsPath []Bytes
}

type Unkown

type Unkown struct {
	Matched int
}

*

  • Initital State Code

func (*Unkown) Add

func (unkown *Unkown) Add(bt byte, parser *Parser) (ICode, error)

func (*Unkown) Type

func (unkown *Unkown) Type() CodeType

Directories

Path Synopsis
*
*

Jump to

Keyboard shortcuts

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