package mdx import "github.com/gomarkdown/markdown" import "github.com/gomarkdown/markdown/html" import "github.com/gomarkdown/markdown/parser" import "github.com/d5/tengo/v2" import "bytes" func GetModule() tengo.Importable { return &tengo.BuiltinModule{Attrs:map[string]tengo.Object{ "new": &tengo.BuiltinFunction{ Name: "new", Value: func( args ...tengo.Object, ) (tengo.Object, error){ return MakeDefaultMarkdown(), nil }, }, }} } type Markdown struct { tengo.ObjectImpl MakeParser func() *parser.Parser MakeRenderer func() *html.Renderer } func MakeDefaultMarkdown() *Markdown { return &Markdown{ MakeParser: MakeDefaultParser, MakeRenderer: MakeDefaultRenderer, } } func (md *Markdown) TypeName() string { return "*Markdown" } func (md *Markdown) String() string { if md == nil { return "" } return "&Markdown{...}" } func (md *Markdown) Render( data []byte, ) ([]byte, error) { doc := md.MakeParser().Parse(data) rendered := markdown.Render(doc, md.MakeRenderer()) return rendered, nil } func (md *Markdown) CanCall() bool { return md != nil } func (md *Markdown) Call( args ...tengo.Object, ) (tengo.Object, error) { var b bytes.Buffer for _, arg := range args { str, ok := tengo.ToString(arg) if !ok { return nil, tengo.ErrInvalidArgumentType{ Name: "v", Expected: "stringer", Found: arg.TypeName(), } } b.Write([]byte(str)) } rendered, err := md.Render(b.Bytes()) if err != nil { return nil, err } return tengo.FromInterface(rendered) } func MakeDefaultParser() *parser.Parser { return parser.NewWithExtensions( parser.CommonExtensions | parser.AutoHeadingIDs | parser.NoEmptyLineBeforeBlock | parser.Attributes | parser.Tables, ) } func MakeDefaultRenderer() *html.Renderer { return html.NewRenderer( html.RendererOptions{ Flags: html.CommonFlags | html.HrefTargetBlank, }, ) }