package impor import "fmt" import "errors" import "slices" import "strings" import "html/template" import "git.tebibyte.media/sashakoshka/step" var _ step.FuncProviderFor = new(Provider) var _ step.Configurable = new(Provider) // Provider provides import functions. type Provider struct { config step.Meta } // Package fulfills the step.Provider interface. func (this *Provider) Package () string { return "import" } func (this *Provider) Configure (config step.Meta) error { this.config = config return nil } // FuncMapFor fulfills the step.FuncProviderFor interface. func (this *Provider) FuncMapFor (document *step.Document) template.FuncMap { stat := &state { config: this.config, document: document, } return template.FuncMap { "cancel": stat.funcCancel, "create": stat.funcCreate, "createHTML": stat.funcCreateHTML, "execute": stat.funcExecute, "include": stat.funcInclude, "includeHTML": stat.funcIncludeHTML, "config": stat.funcConfig, "configList": stat.funcConfigList, } } type state struct { config step.Meta document *step.Document } func (this *state) funcPanic (message any) (string, error) { if err, ok := message.(error); ok { return "", err } else { return "", errors.New(fmt.Sprint(message)) } } func (this *state) funcCancel () (string, error) { return "", step.ErrExecutionCanceled } func (this *state) funcCreate (name string, arguments ...any) (string, error) { return this.funcInclude(name, arguments) } func (this *state) funcCreateHTML (name string, arguments ...any) (template.HTML, error) { return this.funcIncludeHTML(name, arguments) } func (this *state) funcExecute (name string, data any) (step.ExecutionResult, error) { name, err := this.document.Rel(name) if err != nil { return step.ExecutionResult { }, err } document, err := this.document.Environment().LoadRelative ( name, this.document) if err != nil { return step.ExecutionResult { }, err } builder := strings.Builder { } err = document.Execute(&builder, step.ExecutionData { Data: data }) if err != nil { return step.ExecutionResult { }, err } return step.ExecutionResult { Author: document.Author, Title: document.Title, Extends: document.Extends, Meta: document.Meta, Body: template.HTML(builder.String()), }, nil } func (this *state) funcInclude (name string, data any) (string, error) { result, err := this.funcIncludeHTML(name, data) return string(result), err } func (this *state) funcIncludeHTML (name string, data any) (template.HTML, error) { result, err := this.funcExecute(name, data) if err != nil { return "", err } return result.Body, nil } func (this *state) funcConfig (key string) string { if this.config == nil { return "" } return this.config.Get(key) } func (this *state) funcConfigList (key string) []string { if this.config == nil { return nil } // config is considered immutable, time to enforce it return slices.Clone(this.config[key]) }