You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
77 lines
1.7 KiB
77 lines
1.7 KiB
package render
|
|
|
|
import (
|
|
"context"
|
|
"errors"
|
|
"fmt"
|
|
"io"
|
|
)
|
|
|
|
var ErrNotFound = errors.New("not found")
|
|
|
|
func New(parser Parser, engines ...Engine) *Render {
|
|
return &Render{
|
|
parser: parser,
|
|
engines: engines,
|
|
}
|
|
}
|
|
|
|
type Render struct {
|
|
engines []Engine
|
|
parser Parser
|
|
}
|
|
|
|
type Execute func(ctx context.Context, wr io.Writer, data interface{}, params Params) error
|
|
|
|
type Engine interface {
|
|
Support(context.Context, Reference) bool
|
|
Load(ctx context.Context, reference Reference) (Execute, error)
|
|
}
|
|
|
|
type Parser func(ctx context.Context, name string, opts ...Option) (Reference, error)
|
|
|
|
// Add add engine. This function is not thread-safe.
|
|
func (e *Render) Add(engine ...Engine) {
|
|
e.engines = append(e.engines, engine...)
|
|
}
|
|
|
|
func (e *Render) WithParser(parser Parser) *Render {
|
|
return New(parser, e.engines...)
|
|
}
|
|
|
|
func (e *Render) Load(ctx context.Context, reference Reference) (Execute, error) {
|
|
for _, engine := range e.engines {
|
|
if engine.Support(ctx, reference) {
|
|
exec, err := engine.Load(ctx, reference)
|
|
if err != nil {
|
|
return nil, fmt.Errorf("render load:%w", err)
|
|
}
|
|
|
|
return exec, nil
|
|
}
|
|
}
|
|
|
|
return nil, fmt.Errorf("loader:%w", ErrNotFound)
|
|
}
|
|
|
|
func (e *Render) Parse(ctx context.Context, name string, opts ...Option) (Reference, error) {
|
|
return e.parser(ctx, name, opts...)
|
|
}
|
|
|
|
func (e *Render) Execute(ctx context.Context, wr io.Writer, name string, data interface{}, opts ...Option) error {
|
|
reference, rerr := e.parser(ctx, name, opts...)
|
|
if rerr != nil {
|
|
return fmt.Errorf("parse: %w", rerr)
|
|
}
|
|
|
|
execute, err := e.Load(ctx, reference)
|
|
if err != nil {
|
|
return fmt.Errorf("engine load:%w", err)
|
|
}
|
|
|
|
if err := execute(ctx, wr, data, reference.Params); err != nil {
|
|
return fmt.Errorf("render execute:%w", err)
|
|
}
|
|
|
|
return nil
|
|
}
|
|
|