func (engine *TextEngine) VisitImage(con booklit.Image) error {
	engine.data = con
	return engine.setTmpl("image")
}
VisitImage renders con using image.tmpl.
package render
import (
	"bytes"
	"errors"
	"fmt"
	"io"
	"io/ioutil"
	"os"
	"path/filepath"
	"strings"
	"text/template"
	"time"
	"github.com/vito/booklit"
	"github.com/vito/booklit/render/text"
)
var initTextTmpl *template.Template
var TextFuncs = template.FuncMap{
	"render": func(booklit.Content) (string, error) {
		return "", errors.New("render stubbed out")
	},
	"url": func(ext string, tag booklit.Tag) (string, error) {
		return "", errors.New("url stubbed out")
	},
	"htmlURL": func(tag booklit.Tag) string {
		return sectionURL("html", tag.Section, tag.Anchor)
	},
	"stripAux": booklit.StripAux,
	"joinLines": func(prefix string, str string) string {
		return strings.Join(strings.Split(str, "\n"), "\n"+prefix)
	},
}
func init() {
	initTextTmpl = template.New("engine").Funcs(TextFuncs)
	for _, asset := range text.AssetNames() {
		info, err := text.AssetInfo(asset)
		if err != nil {
			panic(err)
		}
		content := strings.TrimRight(string(text.MustAsset(asset)), "\n")
		_, err = initTextTmpl.New(filepath.Base(info.Name())).Parse(content)
		if err != nil {
			panic(err)
		}
	}
}
type TextEngine struct {
	fileExtension string
	tmpl         *template.Template
	tmplModTimes map[string]time.Time
	template *template.Template
	data     interface{}
}
func NewTextEngine(fileExtension string) *TextEngine {
	engine := &TextEngine{
		fileExtension: fileExtension,
		tmplModTimes: map[string]time.Time{},
	}
	engine.resetTmpl()
	return engine
}
func (engine *TextEngine) resetTmpl() {
	engine.tmpl = template.Must(initTextTmpl.Clone())
	engine.tmpl.Funcs(template.FuncMap{
		"render": engine.subRender,
		"url": func(tag booklit.Tag) string {
			return sectionURL(engine.FileExtension(), tag.Section, tag.Anchor)
		},
	})
}
func (engine *TextEngine) LoadTemplates(templatesDir string) error {
	templates, err := filepath.Glob(filepath.Join(templatesDir, "*.tmpl"))
	if err != nil {
		return err
	}
	var shouldReload bool
	for _, path := range templates {
		info, err := os.Stat(path)
		if err != nil {
			return err
		}
		modTime := info.ModTime()
		lastModTime, found := engine.tmplModTimes[path]
		if !found || modTime.After(lastModTime) {
			shouldReload = true
		}
		engine.tmplModTimes[path] = modTime
	}
	if !shouldReload {
		return nil
	}
	engine.resetTmpl()
	for _, path := range templates {
		content, err := ioutil.ReadFile(path)
		if err != nil {
			return err
		}
		trimmed := strings.TrimRight(string(content), "\n")
		_, err = engine.tmpl.New(filepath.Base(path)).Parse(trimmed)
		if err != nil {
			return err
		}
	}
	return nil
}
func (engine *TextEngine) FileExtension() string {
	return engine.fileExtension
}
func (engine *TextEngine) URL(tag booklit.Tag) string {
	return sectionURL(engine.FileExtension(), tag.Section, tag.Anchor)
}
func (engine *TextEngine) RenderSection(out io.Writer, con *booklit.Section) error {
	tmpl := "page"
	if con.Style != "" {
		tmpl = con.Style + "-page"
	}
	engine.data = con
	err := engine.setTmpl(tmpl)
	if err != nil {
		return err
	}
	return engine.render(out)
}
func (engine *TextEngine) VisitString(con booklit.String) error {
	engine.data = con
	return engine.setTmpl("string")
}
func (engine *TextEngine) VisitReference(con *booklit.Reference) error {
	engine.data = con
	return engine.setTmpl("reference")
}
func (engine *TextEngine) VisitSection(con *booklit.Section) error {
	tmpl := "section"
	if con.Style != "" {
		tmpl = con.Style
	}
	engine.data = con
	return engine.setTmpl(tmpl)
}
func (engine *TextEngine) VisitSequence(con booklit.Sequence) error {
	engine.data = con
	return engine.setTmpl("sequence")
}
func (engine *TextEngine) VisitParagraph(con booklit.Paragraph) error {
	engine.data = con
	return engine.setTmpl("paragraph")
}
func (engine *TextEngine) VisitPreformatted(con booklit.Preformatted) error {
	engine.data = con
	return engine.setTmpl("preformatted")
}
func (engine *TextEngine) VisitTableOfContents(con booklit.TableOfContents) error {
	engine.data = con.Section
	return engine.setTmpl("toc")
}
func (engine *TextEngine) VisitStyled(con booklit.Styled) error {
	engine.data = con
	return engine.setTmpl(string(con.Style))
}
func (engine *TextEngine) VisitTarget(con booklit.Target) error {
	engine.data = con
	return engine.setTmpl("target")
}