package http
import (
"bytes"
"embed"
"html/template"
"log"
"os"
"time"
"github.com/spf13/pflag"
"github.com/rclone/rclone/fs/config/flags"
)
// TemplateHelp returns a string that describes how to use a custom template
func TemplateHelp(prefix string) string {
help := `
#### Template
` + "`--{{ .Prefix }}template`" + ` allows a user to specify a custom markup template for HTTP
and WebDAV serve functions. The server exports the following markup
to be used within the template to server pages:
| Parameter | Description |
| :---------- | :---------- |
| .Name | The full path of a file/directory. |
| .Title | Directory listing of .Name |
| .Sort | The current sort used. This is changeable via ?sort= parameter |
| | Sort Options: namedirfirst,name,size,time (default namedirfirst) |
| .Order | The current ordering used. This is changeable via ?order= parameter |
| | Order Options: asc,desc (default asc) |
| .Query | Currently unused. |
| .Breadcrumb | Allows for creating a relative navigation |
|-- .Link | The relative to the root link of the Text. |
|-- .Text | The Name of the directory. |
| .Entries | Information about a specific file/directory. |
|-- .URL | The 'url' of an entry. |
|-- .Leaf | Currently same as 'URL' but intended to be 'just' the name. |
|-- .IsDir | Boolean for if an entry is a directory or not. |
|-- .Size | Size in Bytes of the entry. |
|-- .ModTime | The UTC timestamp of an entry. |
`
tmpl, err := template.New("template help").Parse(help)
if err != nil {
log.Fatal("Fatal error parsing template", err)
}
data := struct {
Prefix string
}{
Prefix: prefix,
}
buf := &bytes.Buffer{}
err = tmpl.Execute(buf, data)
if err != nil {
log.Fatal("Fatal error executing template", err)
}
return buf.String()
}
// TemplateConfig for the templating functionality
type TemplateConfig struct {
Path string
}
// AddFlagsPrefix for the templating functionality
func (cfg *TemplateConfig) AddFlagsPrefix(flagSet *pflag.FlagSet, prefix string) {
flags.StringVarP(flagSet, &cfg.Path, prefix+"template", "", cfg.Path, "User-specified template")
}
// AddTemplateFlagsPrefix for the templating functionality
func AddTemplateFlagsPrefix(flagSet *pflag.FlagSet, prefix string, cfg *TemplateConfig) {
cfg.AddFlagsPrefix(flagSet, prefix)
}
// DefaultTemplateCfg returns a new config which can be customized by command line flags
func DefaultTemplateCfg() TemplateConfig {
return TemplateConfig{}
}
// AfterEpoch returns the time since the epoch for the given time
func AfterEpoch(t time.Time) bool {
return t.After(time.Time{})
}
// Assets holds the embedded filesystem for the default template
//
//go:embed templates
var Assets embed.FS
// GetTemplate returns the HTML template for serving directories via HTTP/WebDAV
func GetTemplate(tmpl string) (*template.Template, error) {
var readFile = os.ReadFile
if tmpl == "" {
tmpl = "templates/index.html"
readFile = Assets.ReadFile
}
data, err := readFile(tmpl)
if err != nil {
return nil, err
}
funcMap := template.FuncMap{
"afterEpoch": AfterEpoch,
}
tpl, err := template.New("index").Funcs(funcMap).Parse(string(data))
if err != nil {
return nil, err
}
return tpl, nil
}