Skip to content
Snippets Groups Projects
Select Git revision
  • 097c706ff1857fc825a36237d68c7f60119937ff
  • master default protected
  • feature/PRXS-3383-CollectionsSort
  • feature/2781-SpacesLoggingMiddleware
  • feature/PRXS-3421-ImplementNewRefAPI
  • feature/PRXS-3143-3235-ReferenceOptions
  • feature/PRXS-3143-LimitReferenceFields
  • feature/PRXS-3234-FeaturePruneIdents
  • PRXS-3421-RecursiveReferences
  • feature/3109-SerializeFeature
  • release/0.33
  • feature/3109-RecoverySchema
  • feature/3109-feature
  • fix/PRXS-3369-ValidateFields
  • refactor/PRXS-3306-MovePkgGroup1
  • refactor/6-pkg-refactor-expr
  • fix/PRXS-3360-TemplateBuilderPatch
  • feature/3293-MongoV2
  • feature/3272-GoVersionUp
  • feature/PRXS-3218-HideTemplateActions
  • feature/PRXS-3234-PruneIdents
  • v0.33.1
  • v0.32.0
  • v0.31.1
  • v0.31.0
  • v0.30.0
  • v0.29.0
  • v0.28.0
  • v0.27.0-alpha.1+16
  • v0.27.0-alpha.1+15
  • v0.27.0-alpha.1+14
  • v0.27.0-alpha.1+13
  • v0.27.0-alpha.1+12
  • v0.27.0-alpha.1+11
  • v0.27.0-alpha.1+10
  • v0.27.0-alpha.1+9
  • v0.27.0-alpha.1+8
  • v0.27.0-alpha.1+7
  • v0.27.0-alpha.1+6
  • v0.27.0-alpha.1+5
  • v0.27.0-alpha.1+4
41 results

collaborator.go

Blame
  • builder.go 3.25 KiB
    package template
    
    import (
    	"bytes"
    	"context"
    	"text/template"
    
    	"git.perx.ru/perxis/perxis-go/pkg/content"
    )
    
    type Builder struct {
    	ctx     context.Context
    	cnt     *content.Content
    	SpaceID string
    	EnvID   string
    	funcs   template.FuncMap
    	data    map[string]interface{}
    }
    
    func NewBuilder(cnt *content.Content, space, env string) *Builder {
    	return &Builder{
    		ctx:     context.Background(),
    		cnt:     cnt,
    		SpaceID: space,
    		EnvID:   env,
    		funcs:   make(template.FuncMap),
    	}
    }
    
    func (b *Builder) getFuncs() template.FuncMap {
    	return template.FuncMap{
    		"lookup": getLookup(b),
    		"system": getSystem(b),
    	}
    }
    
    func (b *Builder) WithData(data map[string]interface{}) *Builder {
    	bld := *b
    	bld.data = data
    	return &bld
    }
    
    func (b *Builder) WithKV(kv ...any) *Builder {
    	bld := *b
    	if bld.data == nil {
    		bld.data = make(map[string]interface{}, 10)
    	}
    	for i := 0; i < len(kv)-1; i += 2 {
    		k, _ := kv[i].(string)
    		v := kv[i+1]
    		if k != "" && v != nil {
    			bld.data[k] = v
    		}
    	}
    	return &bld
    }
    
    func (b *Builder) GetData() map[string]interface{} {
    	return b.data
    }
    
    func (b *Builder) WithSpace(space, env string) *Builder {
    	bld := *b
    	bld.SpaceID = space
    	bld.EnvID = env
    	return &bld
    }
    
    func (b *Builder) WithContext(ctx context.Context) *Builder {
    	bld := *b
    	bld.ctx = ctx
    	return &bld
    }
    
    func (b *Builder) Context() context.Context {
    	return b.ctx
    }
    
    func (b *Builder) Template() *template.Template {
    	return template.New("main").Funcs(b.getFuncs())
    }
    
    func (b *Builder) Execute(str string, data ...any) (string, error) {
    	t := b.Template()
    	buf := new(bytes.Buffer)
    	t, err := t.Parse(str)
    	if err != nil {
    		return "", err
    	}
    	if err = t.Execute(buf, b.getData(data...)); err != nil {
    		return "", err
    	}
    	return buf.String(), nil
    }
    
    func (b *Builder) ExecuteList(str []string, data ...any) ([]string, error) {
    	t := b.Template()
    	result := make([]string, len(str))
    	buffer := new(bytes.Buffer)
    	for i, tmpl := range str {
    		if tmpl == "" {
    			continue
    		}
    		t, err := t.Parse(tmpl)
    		if err != nil {
    			return []string{}, err
    		}
    		if err = t.Execute(buffer, b.getData(data...)); err != nil {
    			return []string{}, err
    		}
    		result[i] = buffer.String()
    		buffer.Reset()
    	}
    	return result, nil
    }
    
    func (b *Builder) ExecuteMap(str map[string]interface{}, data ...any) (map[string]interface{}, error) {
    	result := make(map[string]interface{}, len(str))
    	for k, v := range str {
    		switch t := v.(type) {
    		case string:
    			value, err := b.Execute(t, data...)
    			if err != nil {
    				return nil, err
    			}
    			v = value
    		case []string:
    			values, err := b.ExecuteList(append([]string{k}, t...), data...)
    			if err != nil {
    				return nil, err
    			}
    			k = values[0]
    			vv := make([]interface{}, 0, len(t))
    			for _, val := range values[1:] {
    				vv = append(vv, val)
    			}
    			v = vv
    		}
    
    		result[k] = v
    	}
    	return result, nil
    }
    
    func (b *Builder) getData(data ...any) any {
    	if len(data) == 0 {
    		return b.data
    	}
    
    	var res map[string]interface{}
    	for _, v := range data {
    		if m, ok := v.(map[string]interface{}); ok && b.data != nil {
    			res = mergeMaps(b.data, m)
    		}
    	}
    	if res != nil {
    		return res
    	}
    
    	return data[0]
    }
    
    func mergeMaps(in ...map[string]interface{}) map[string]interface{} {
    	out := make(map[string]interface{})
    	for _, i := range in {
    		for k, v := range i {
    			out[k] = v
    		}
    	}
    	return out
    }