1
0
Fork 0
mirror of https://github.com/Eggbertx/gochan.git synced 2025-08-02 02:36:24 -07:00

Make templates private, accessible via template filename

This commit is contained in:
Eggbertx 2023-12-19 13:32:25 -08:00
parent 4c73891ff5
commit b252e65ba7
15 changed files with 261 additions and 267 deletions

View file

@ -1,6 +1,7 @@
-- testing manage page registering from Lua plugins
local strings = require("strings")
local manage = require("manage")
local serverutil = require("serverutil")
manage.register_manage_page("mgmtplugintest",
"Staff Plugin Testing",
@ -26,7 +27,7 @@ manage.register_manage_page("templateplugintest",
end
buf = strings.new_builder()
err = minify_template(tmpl, {
err = serverutil.minify_template(tmpl, {
staff = staff
}, buf, "text/html")

View file

@ -54,7 +54,7 @@ func BuildBoardPages(board *gcsql.Board) error {
Int("boardID", board.ID).
Str("boardDir", board.Dir)
defer errEv.Discard()
err := gctemplates.InitTemplates("boardpage")
err := gctemplates.InitTemplates(gctemplates.BoardPage)
if err != nil {
errEv.Err(err).Caller().Msg("unable to initialize boardpage template")
return err

View file

@ -84,7 +84,7 @@ func BuildFrontPage() error {
errEv := gcutil.LogError(nil).
Str("template", "front")
defer errEv.Discard()
err := gctemplates.InitTemplates("front")
err := gctemplates.InitTemplates(gctemplates.FrontPage)
if err != nil {
errEv.Err(err).Caller().Send()
return errors.New("Error loading front page template: " + err.Error())
@ -150,7 +150,7 @@ func BuildPageFooter(writer io.Writer) (err error) {
// BuildJS minifies (if enabled) consts.js, which is built from a template
func BuildJS() error {
// build consts.js from template
err := gctemplates.InitTemplates("js")
err := gctemplates.InitTemplates(gctemplates.JsConsts)
errEv := gcutil.LogError(nil).Str("building", "consts.js")
defer errEv.Discard()
if err != nil {

View file

@ -95,7 +95,7 @@ func BuildCatalog(boardID int) error {
errEv := gcutil.LogError(nil).
Str("building", "catalog").
Int("boardID", boardID)
err := gctemplates.InitTemplates("catalog")
err := gctemplates.InitTemplates(gctemplates.Catalog)
if err != nil {
errEv.Err(err).Send()
return err

View file

@ -52,7 +52,7 @@ func BuildThreadPages(op *gcsql.Post) error {
errEv.Caller().Msg("non-OP passed to BuildThreadPages")
return gcsql.ErrNotTopPost
}
err := gctemplates.InitTemplates("threadpage")
err := gctemplates.InitTemplates(gctemplates.ThreadPage)
if err != nil {
errEv.Err(err).Caller().Send()
return err

View file

@ -15,6 +15,7 @@ import (
"github.com/gochan-org/gochan/pkg/gcutil"
"github.com/gochan-org/gochan/pkg/manage"
"github.com/gochan-org/gochan/pkg/posting/uploads"
"github.com/gochan-org/gochan/pkg/server/serverutil"
luar "layeh.com/gopher-luar"
"github.com/cjoudrey/gluahttp"
@ -102,6 +103,7 @@ func preloadLua() {
lState.PreloadModule("gctemplates", gctemplates.PreloadModule)
lState.PreloadModule("manage", manage.PreloadModule)
lState.PreloadModule("uploads", uploads.PreloadModule)
lState.PreloadModule("serverutil", serverutil.PreloadModule)
lState.SetGlobal("_GOCHAN_VERSION", lua.LString(config.GetVersion().String()))
}

View file

@ -1,11 +1,6 @@
package gctemplates
import (
"html/template"
"io"
"github.com/gochan-org/gochan/pkg/gcplugin/luautil"
"github.com/gochan-org/gochan/pkg/server/serverutil"
lua "github.com/yuin/gopher-lua"
luar "layeh.com/gopher-luar"
)
@ -19,25 +14,11 @@ func PreloadModule(l *lua.LState) int {
for i := 0; i < l.GetTop(); i++ {
tmplPaths = append(tmplPaths, l.CheckString(i+1))
}
tmpl, err := LoadTemplate(tmplPaths...)
tmpl, err := loadTemplate(tmplPaths...)
l.Push(luar.New(l, tmpl))
l.Push(luar.New(l, err))
return 2
},
"minify_template": func(l *lua.LState) int {
tmplUD := l.CheckUserData(1)
tmpl := tmplUD.Value.(*template.Template)
dataTable := l.CheckTable(2)
data := map[string]interface{}{}
dataTable.ForEach(func(l1, l2 lua.LValue) {
data[l1.String()] = luautil.LValueToInterface(l, l2)
})
writer := l.CheckUserData(3).Value.(io.Writer)
mediaType := l.CheckString(4)
err := serverutil.MinifyTemplate(tmpl, data, writer, mediaType)
l.Push(luar.New(l, err))
return 1
},
"parse_template": func(l *lua.LState) int {
tmplName := l.CheckString(1)
tmplData := l.CheckString(2)

View file

@ -1,6 +1,7 @@
package gctemplates
import (
"errors"
"fmt"
"html/template"
"os"
@ -10,54 +11,184 @@ import (
"github.com/gochan-org/gochan/pkg/gcsql"
)
var (
Banpage *template.Template
Captcha *template.Template
Catalog *template.Template
ErrorPage *template.Template
FrontPage *template.Template
BoardPage *template.Template
JsConsts *template.Template
ManageAnnouncements *template.Template
ManageAppeals *template.Template
ManageBans *template.Template
ManageBoards *template.Template
ManageDashboard *template.Template
ManageFileBans *template.Template
ManageFixThumbnails *template.Template
ManageIPSearch *template.Template
ManageLogin *template.Template
ManageNameBans *template.Template
ManageRecentPosts *template.Template
ManageReports *template.Template
ManageSections *template.Template
ManageStaff *template.Template
ManageTemplateOverride *template.Template
ManageThreadAttrs *template.Template
ManageWordfilters *template.Template
ManageViewLog *template.Template
MoveThreadPage *template.Template
PageHeader *template.Template
PageFooter *template.Template
PostEdit *template.Template
ThreadPage *template.Template
const (
BanPage = "banpage.html"
BoardPage = "boardpage.html"
Captcha = "captcha.html"
Catalog = "catalog.html"
JsConsts = "consts.js"
ErrorPage = "error.html"
FrontPage = "front.html"
ManageAnnouncements = "manage_announcements.html"
ManageAppeals = "manage_appeals.html"
ManageBans = "manage_bans.html"
ManageBoards = "manage_boards.html"
ManageDashboard = "manage_dashboard.html"
ManageFileBans = "manage_filebans.html"
ManageFixThumbnails = "manage_fixthumbnails.html"
ManageIPSearch = "manage_ipsearch.html"
ManageLogin = "manage_login.html"
ManageNameBans = "manage_namebans.html"
ManageRecentPosts = "manage_recentposts.html"
ManageReports = "manage_reports.html"
ManageSections = "manage_sections.html"
ManageStaff = "manage_staff.html"
ManageTemplates = "manage_templateoverride.html"
ManageThreadAttrs = "manage_threadattrs.html"
ManageViewLog = "manage_viewlog.html"
ManageWordfilters = "manage_wordfilters.html"
MoveThreadPage = "movethreadpage.html"
PageFooter = "page_footer.html"
PageHeader = "page_header.html"
PostEdit = "post_edit.html"
ThreadPage = "threadpage.html"
)
func LoadTemplate(files ...string) (*template.Template, error) {
var (
ErrUnrecognizedTemplate = errors.New("unrecognized template")
templateMap = map[string]*gochanTemplate{
BanPage: {
files: []string{"banpage.html", "page_footer.html"},
},
BoardPage: {
files: []string{"boardpage.html", "topbar.html", "post.html", "page_header.html", "postbox.html", "page_footer.html"},
},
Captcha: {
files: []string{"captcha.html"},
},
Catalog: {
files: []string{"catalog.html", "topbar.html", "page_header.html", "page_footer.html"},
},
JsConsts: {
files: []string{"consts.js"},
},
ErrorPage: {
files: []string{"error.html"},
},
FrontPage: {
files: []string{"front.html", "topbar.html", "front_intro.html", "page_header.html", "page_footer.html"},
},
ManageAnnouncements: {
files: []string{"manage_announcements.html", "page_header.html", "topbar.html", "page_footer.html"},
},
ManageAppeals: {
files: []string{"manage_appeals.html"},
},
ManageBans: {
files: []string{"manage_bans.html"},
},
ManageBoards: {
files: []string{"manage_boards.html"},
},
ManageDashboard: {
files: []string{"manage_dashboard.html"},
},
ManageFileBans: {
files: []string{"manage_filebans.html"},
},
ManageFixThumbnails: {
files: []string{"manage_fixthumbnails.html"},
},
ManageIPSearch: {
files: []string{"manage_ipsearch.html"},
},
ManageLogin: {
files: []string{"manage_login.html"},
},
ManageNameBans: {
files: []string{"manage_namebans.html"},
},
ManageRecentPosts: {
files: []string{"manage_recentposts.html"},
},
ManageReports: {
files: []string{"manage_reports.html"},
},
ManageSections: {
files: []string{"manage_sections.html"},
},
ManageStaff: {
files: []string{"manage_staff.html"},
},
ManageTemplates: {
files: []string{"manage_templateoverride.html"},
},
ManageThreadAttrs: {
files: []string{"manage_threadattrs.html"},
},
ManageViewLog: {
files: []string{"manage_viewlog.html"},
},
ManageWordfilters: {
files: []string{"manage_wordfilters.html"},
},
MoveThreadPage: {
files: []string{"movethreadpage.html", "page_header.html", "topbar.html", "page_footer.html"},
},
PageFooter: {
files: []string{"page_footer.html"},
},
PageHeader: {
files: []string{"page_header.html", "topbar.html"},
},
PostEdit: {
files: []string{"post_edit.html", "page_header.html", "topbar.html", "page_footer.html"},
},
ThreadPage: {
files: []string{"threadpage.html", "topbar.html", "post.html", "page_header.html", "postbox.html", "page_footer.html"},
},
}
)
type gochanTemplate struct {
files []string
tmpl *template.Template
}
func (gt *gochanTemplate) Load() (err error) {
gt.tmpl, err = loadTemplate(gt.files...)
return err
}
func (gt *gochanTemplate) Template() *template.Template {
return gt.tmpl
}
func GetTemplate(name string) (*template.Template, error) {
gctmpl, ok := templateMap[name]
if !ok {
fmt.Printf("Unrecognized template %q\n", name)
return nil, ErrUnrecognizedTemplate
}
if gctmpl.tmpl != nil {
return gctmpl.tmpl, nil
}
var err error
gctmpl.tmpl, err = loadTemplate(gctmpl.files...)
return gctmpl.tmpl, err
}
func loadTemplate(files ...string) (*template.Template, error) {
var templates []string
templateDir := config.GetSystemCriticalConfig().TemplateDir
var foundFiles []string
for i, file := range files {
foundFiles = append(foundFiles, file)
templates = append(templates, file)
tmplPath := path.Join(templateDir, "override", file)
if _, err := os.Stat(tmplPath); !os.IsNotExist(err) {
files[i] = tmplPath
if _, err := os.Stat(tmplPath); err == nil {
foundFiles[i] = tmplPath
} else if os.IsNotExist(err) {
foundFiles[i] = path.Join(templateDir, file)
} else {
files[i] = path.Join(templateDir, file)
return nil, err
}
}
return template.New(templates[0]).Funcs(funcMap).ParseFiles(files...)
tmpl, err := template.New(templates[0]).Funcs(funcMap).ParseFiles(foundFiles...)
return tmpl, templateError(templates[0], err)
}
func ParseTemplate(name, tmplStr string) (*template.Template, error) {
@ -70,209 +201,31 @@ func templateError(name string, err error) error {
}
templateDir := config.GetSystemCriticalConfig().TemplateDir
return fmt.Errorf("failed loading template '%s/%s': %s",
return fmt.Errorf("failed loading template '%s: %s': %s",
templateDir, name, err.Error())
}
// InitTemplates loads the given templates by name. If no parameters are given,
// or the first one is "all", all templates are (re)loaded
// all templates are (re)loaded
func InitTemplates(which ...string) error {
err := gcsql.ResetBoardSectionArrays()
if err != nil {
return err
}
if len(which) == 0 || which[0] == "all" {
return templateLoading("", true)
if which == nil {
// no templates specified
for t := range templateMap {
if err = templateMap[t].Load(); err != nil {
return err
}
}
}
for _, t := range which {
if err = templateLoading(t, false); err != nil {
if _, err = GetTemplate(t); err != nil {
return err
}
}
return nil
}
func templateLoading(t string, buildAll bool) error {
var err error
if buildAll || t == "banpage" {
Banpage, err = LoadTemplate("banpage.html", "page_footer.html")
if err != nil {
return templateError("banpage.html", err)
}
}
if buildAll || t == "captcha" {
Captcha, err = LoadTemplate("captcha.html")
if err != nil {
return templateError("captcha.html", err)
}
}
if buildAll || t == "catalog" {
Catalog, err = LoadTemplate("catalog.html", "topbar.html", "page_header.html", "page_footer.html")
if err != nil {
return templateError("catalog.html", err)
}
}
if buildAll || t == "error" {
ErrorPage, err = LoadTemplate("error.html")
if err != nil {
return templateError("error.html", err)
}
}
if buildAll || t == "front" {
FrontPage, err = LoadTemplate("front.html", "topbar.html", "front_intro.html", "page_header.html", "page_footer.html")
if err != nil {
return templateError("front.html", err)
}
}
if buildAll || t == "boardpage" {
BoardPage, err = LoadTemplate("boardpage.html", "topbar.html", "post.html", "page_header.html", "postbox.html", "page_footer.html")
if err != nil {
return templateError("boardpage.html", err)
}
}
if buildAll || t == "threadpage" {
ThreadPage, err = LoadTemplate("threadpage.html", "topbar.html", "post.html", "page_header.html", "postbox.html", "page_footer.html")
if err != nil {
return templateError("threadpage.html", err)
}
}
if buildAll || t == "postedit" {
PostEdit, err = LoadTemplate("post_edit.html", "page_header.html", "topbar.html", "page_footer.html")
if err != nil {
return templateError("threadpage.html", err)
}
}
if buildAll || t == "manageannouncements" {
ManageAnnouncements, err = LoadTemplate("manage_announcements.html", "page_header.html", "topbar.html", "page_footer.html")
if err != nil {
return templateError("manage_announcements.html", err)
}
}
if buildAll || t == "manageappeals" {
ManageAppeals, err = LoadTemplate("manage_appeals.html")
if err != nil {
return templateError("manage_appeals.html", err)
}
}
if buildAll || t == "managebans" {
ManageBans, err = LoadTemplate("manage_bans.html")
if err != nil {
return templateError("manage_bans.html", err)
}
}
if buildAll || t == "manageboards" {
ManageBoards, err = LoadTemplate("manage_boards.html")
if err != nil {
return templateError("manage_boards.html", err)
}
}
if buildAll || t == "managetemplateoverride" {
ManageTemplateOverride, err = LoadTemplate("manage_templateoverride.html")
if err != nil {
return templateError("manage_templateoverride.html", err)
}
}
if buildAll || t == "managethreadattrs" {
ManageThreadAttrs, err = LoadTemplate("manage_threadattrs.html")
if err != nil {
return templateError("manage_threadattrs.html", err)
}
}
if buildAll || t == "managesections" {
ManageSections, err = LoadTemplate("manage_sections.html")
if err != nil {
return templateError("manage_sections.html", err)
}
}
if buildAll || t == "managedashboard" {
ManageDashboard, err = LoadTemplate("manage_dashboard.html")
if err != nil {
return templateError("manage_dashboard.html", err)
}
}
if buildAll || t == "managelogin" {
ManageLogin, err = LoadTemplate("manage_login.html")
if err != nil {
return templateError("manage_login.html", err)
}
}
if buildAll || t == "managereports" {
ManageReports, err = LoadTemplate("manage_reports.html")
if err != nil {
return templateError("manage_reports.html", err)
}
}
if buildAll || t == "managefilebans" {
ManageFileBans, err = LoadTemplate("manage_filebans.html")
if err != nil {
return templateError("manage_filebans.html", err)
}
}
if buildAll || t == "managenamebans" {
ManageNameBans, err = LoadTemplate("manage_namebans.html")
if err != nil {
return templateError("manage_namebans.html", err)
}
}
if buildAll || t == "manageipsearch" {
ManageIPSearch, err = LoadTemplate("manage_ipsearch.html")
if err != nil {
return templateError("manage_ipsearch.html", err)
}
}
if buildAll || t == "managerecents" {
ManageRecentPosts, err = LoadTemplate("manage_recentposts.html")
if err != nil {
return templateError("manage_recentposts.html", err)
}
}
if buildAll || t == "managewordfilters" {
ManageWordfilters, err = LoadTemplate("manage_wordfilters.html")
if err != nil {
return templateError("manage_wordfilters.html", err)
}
}
if buildAll || t == "managestaff" {
ManageStaff, err = LoadTemplate("manage_staff.html")
if err != nil {
return templateError("manage_staff.html", err)
}
}
if buildAll || t == "manageviewlog" {
ManageViewLog, err = LoadTemplate("manage_viewlog.html")
if err != nil {
return templateError("manage_viewlog.html", err)
}
}
if buildAll || t == "managefixthumbnails" {
ManageFixThumbnails, err = LoadTemplate("manage_fixthumbnails.html")
if err != nil {
return templateError("manage_viewlog.html", err)
}
}
if buildAll || t == "movethreadpage" {
MoveThreadPage, err = LoadTemplate("movethreadpage.html", "page_header.html", "topbar.html", "page_footer.html")
if err != nil {
return templateError("movethreadpage.html", err)
}
}
if buildAll || t == "pageheader" {
PageHeader, err = LoadTemplate("page_header.html", "topbar.html")
if err != nil {
return templateError("page_header.html", err)
}
}
if buildAll || t == "pagefooter" {
PageFooter, err = LoadTemplate("page_footer.html")
if err != nil {
return templateError("page_footer.html", err)
}
}
if buildAll || t == "js" {
JsConsts, err = LoadTemplate("consts.js")
if err != nil {
return templateError("consts.js", err)
}
}
return nil
}

View file

@ -73,7 +73,6 @@ func registerAdminPages() {
if announcement.ID < 1 {
return "", fmt.Errorf("no announcement found with id %d", editID)
}
fmt.Println(announcement)
if request.PostFormValue("doedit") == "Submit" {
// announcement update submitted
announcement.Subject = request.PostFormValue("subject")
@ -585,9 +584,9 @@ func registerAdminPages() {
Callback: func(writer http.ResponseWriter, request *http.Request, staff *gcsql.Staff, wantsJSON bool, infoEv, errEv *zerolog.Event) (output interface{}, err error) {
buf := bytes.NewBufferString("")
serverutil.MinifyTemplate(gctemplates.ManageTemplateOverride, map[string]any{
"currentTemplate": "manage_stuff.html",
"templateText": "template goes here",
serverutil.MinifyTemplate(gctemplates.ManageTemplates, map[string]any{
"template": "manage_stuff.html",
"templateText": "template goes here",
}, buf, "text/html")
return buf.String(), nil
}},

View file

@ -18,7 +18,7 @@ import (
func showBanpage(ban *gcsql.IPBan, post *gcsql.Post, postBoard *gcsql.Board, writer http.ResponseWriter, _ *http.Request) {
banPageBuffer := bytes.NewBufferString("")
err := serverutil.MinifyTemplate(gctemplates.Banpage, map[string]interface{}{
err := serverutil.MinifyTemplate(gctemplates.BanPage, map[string]interface{}{
"systemCritical": config.GetSystemCriticalConfig(),
"siteConfig": config.GetSiteConfig(),
"boardConfig": config.GetBoardConfig(postBoard.Dir),

View file

@ -51,7 +51,6 @@ func MakePost(writer http.ResponseWriter, request *http.Request) {
Bytes("stack", debug.Stack()).
Msg("Recovered from panic")
debug.PrintStack()
fmt.Println("Recovered from panic in MakePost:", a)
}
errEv.Discard()
infoEv.Discard()

View file

@ -5,6 +5,7 @@ import (
"io"
"github.com/gochan-org/gochan/pkg/config"
"github.com/gochan-org/gochan/pkg/gctemplates"
"github.com/tdewolff/minify"
minifyHTML "github.com/tdewolff/minify/html"
minifyJS "github.com/tdewolff/minify/js"
@ -13,6 +14,10 @@ import (
var minifier *minify.M
type templateRef interface {
string | *template.Template
}
// InitMinifier sets up the HTML/JS/JSON minifier if enabled in gochan.json
func InitMinifier() {
siteConfig := config.GetSiteConfig()
@ -40,8 +45,19 @@ func canMinify(mediaType string) bool {
return false
}
// MinifyTemplate minifies the given template/data (if enabled) and returns any errors
func MinifyTemplate(tmpl *template.Template, data interface{}, writer io.Writer, mediaType string) error {
// MinifyTemplate minifies the given template ref (string or template.Template pointer) and data, and returns any errors
func MinifyTemplate[T templateRef](tmplRef T, data interface{}, writer io.Writer, mediaType string) (err error) {
var tmpl *template.Template
switch ref := any(tmplRef).(type) {
case string:
tmpl, err = gctemplates.GetTemplate(ref)
if err != nil {
return err
}
case *template.Template:
tmpl = ref
}
if !canMinify(mediaType) {
return tmpl.Execute(writer, data)
}

View file

@ -0,0 +1,33 @@
package serverutil
import (
"html/template"
"io"
"github.com/gochan-org/gochan/pkg/gcplugin/luautil"
lua "github.com/yuin/gopher-lua"
luar "layeh.com/gopher-luar"
)
func PreloadModule(l *lua.LState) int {
t := l.NewTable()
l.SetFuncs(t, map[string]lua.LGFunction{
"minify_template": func(l *lua.LState) int {
tmplUD := l.CheckUserData(1)
tmpl := tmplUD.Value.(*template.Template)
dataTable := l.CheckTable(2)
data := map[string]interface{}{}
dataTable.ForEach(func(l1, l2 lua.LValue) {
data[l1.String()] = luautil.LValueToInterface(l, l2)
})
writer := l.CheckUserData(3).Value.(io.Writer)
mediaType := l.CheckString(4)
err := MinifyTemplate(tmpl, data, writer, mediaType)
l.Push(luar.New(l, err))
return 1
},
})
return 1
}

View file

@ -42,8 +42,6 @@ The following are modules that can be loaded via `require("modulename")`. See [.
## gctemplates
- **gctemplates.load_template(files...)**
- Calls [gctemplates.LoadTemplate](https://pkg.go.dev/github.com/gochan-org/gochan/pkg/gctemplates#LoadTemplate) using the given `files` and returns a [Template](https://pkg.go.dev/html/template#Template) and an error object (or nil if there were no errors).
- **gctemplates.minify_template(template, data_table, writer, media_type)**
- Calls [serverutil.MinifyTemplate](https://pkg.go.dev/github.com/gochan-org/gochan/pkg/server/serverutil#MinifyTemplate) with the given `template` object, `data_table` (as variables passed to the template), `writer`, and `media_type`. See [registermgmtpage.lua](./examples/plugins/registermgmtpage.lua) for an example
- **gctemplates.parse_template(template_name string, template_data string)**
- Calls [gctemplates.ParseTemplate](https://pkg.go.dev/github.com/gochan-org/gochan/pkg/gctemplates#ParseTemplate) with the given template name and Go template data, and returns a [Template](https://pkg.go.dev/html/template#Template) and an error object (or nil if there were no errors).
@ -63,6 +61,10 @@ staff_note | string | A private note attached to the ban that only staff can see
- **manage.register_manage_page(action string, title string, perms int, wants_json int, handler func(writer, request, staff, wants_json, info_ev, err_ev))**
- Registers the manage page accessible at /manage/`action` to be handled by `handler`. See [manage.RegisterManagePage](https://pkg.go.dev/github.com/gochan-org/gochan/pkg/manage#RegisterManagePage) for info on how `handler` should be used, or [registermgmtpage.lua](./examples/plugins/registermgmtpage.lua) for an example
## serverutil
- **serverutil.minify_template(template, data_table, writer, media_type)**
- Calls [serverutil.MinifyTemplate](https://pkg.go.dev/github.com/gochan-org/gochan/pkg/server/serverutil#MinifyTemplate) with the given `template` object, `data_table` (as variables passed to the template), `writer`, and `media_type`. See [registermgmtpage.lua](./examples/plugins/registermgmtpage.lua) for an example
## uploads
- **uploads.register_handler(ext string, function(upload, post, board, filePath, thumbPath, catalogThumbPath, infoEv, accessEv, errEv))**
- Registers a function to be called for handling uploaded files with the given extension. See [pdf_thumbnail.lua](./examples//plugins/pdf_thumbnail.lua) for a usage example.

View file

@ -1,8 +1,16 @@
<div style="text-align: center;">
<form action="{{webPath "manage/templates"}}" method="POST" id="template-override">
{{with $.templateText}}
<b>Editing: {{$.currentTemplate}}</b>
<form action="{{webPath "manage/templates"}}" method="POST" id="template-override">
<textarea class="template-text" rows="16" spellcheck="false">{{.templateText}}</textarea>
<input type="submit" name="dooverride" value="Submit" onsubmit="return prompt('Are you sure you want to override the template?')">
<input type="submit" name="cancel" value="Cancel"/>
</form>
<textarea class="template-text" rows="16" spellcheck="false">{{$.templateText}}</textarea>
<input type="submit" name="dooverride" value="Submit" onsubmit="return prompt('Are you sure you want to override the template?')">
<input type="submit" name="cancel" value="Cancel"/>
{{else}}
Select a template: <select name="templateselect">
{{range $t, $template := .templates}}
<option value="$template"></option>
{{end}}
</select>
{{end}}
</form>
</div>