diff --git a/internal/pkg/constraints/const.go b/internal/pkg/constraints/const.go index a1baf7a..b2d368b 100644 --- a/internal/pkg/constraints/const.go +++ b/internal/pkg/constraints/const.go @@ -16,6 +16,9 @@ const ( AllStats AllScene + PipData + PipRender + Defaults = "default" HeadScript = "headScript" diff --git a/internal/theme/twentyfifteen/twentyfifteen.go b/internal/theme/twentyfifteen/twentyfifteen.go index f4feb92..be8ef56 100644 --- a/internal/theme/twentyfifteen/twentyfifteen.go +++ b/internal/theme/twentyfifteen/twentyfifteen.go @@ -41,7 +41,10 @@ func Init(fs embed.FS) { } } -var pipe = wp.HandlePipe(wp.ExecuteHandleFn, widget.MiddleWare(ready, wp.DataHandle)...) +var pipe = wp.HandlePipe(wp.NothingToDo, widget.MiddleWare(ready, + wp.PipeHandle(constraints.PipData, wp.PipeKey, wp.PipeDataHandle), + wp.PipeHandle(constraints.PipRender, wp.PipeKey, wp.PipeRender), +)...) func Hook(h *wp.Handle) { pipe(h) @@ -64,14 +67,14 @@ func configs(h *wp.Handle) { h.CommonComponents() h.Index.SetListPlugin(wp.PostsPlugins(wp.PostPlugin(), wp.GetListPostPlugins(conf.ListPagePlugins, wp.ListPostPlugins())...)) components.WidgetArea(h) - h.PushRender(constraints.AllStats, wp.NewHandleFn(customHeader, 10)) - h.PushRender(constraints.AllStats, wp.NewHandleFn(wp.IndexRender, 50)) - h.PushRender(constraints.Detail, wp.NewHandleFn(wp.DetailRender, 50)) - h.PushRender(constraints.Detail, wp.NewHandleFn(postThumb, 60)) - h.PushDataHandler(constraints.Detail, wp.NewHandleFn(wp.Details, 100)) - h.PushDataHandler(constraints.AllScene, wp.NewHandleFn(wp.Indexs, 100)) - h.PushDataHandler(constraints.AllScene, wp.NewHandleFn(wp.PreCodeAndStats, 80)) - h.PushDataHandler(constraints.AllScene, wp.NewHandleFn(wp.PreTemplate, 70)) + h.PushRender(constraints.AllStats, wp.NewHandleFn(customHeader, 10, "customHeader")) + h.PushRender(constraints.AllStats, wp.NewHandleFn(wp.IndexRender, 50, "wp.IndexRender")) + h.PushRender(constraints.Detail, wp.NewHandleFn(wp.DetailRender, 50, "wp.DetailRender")) + h.PushRender(constraints.Detail, wp.NewHandleFn(postThumb, 60, "postThumb")) + h.PushDataHandler(constraints.Detail, wp.NewHandleFn(wp.Details, 100, "wp.Details")) + h.PushDataHandler(constraints.AllScene, wp.NewHandleFn(wp.Indexs, 100, "wp.Indexs")) + h.PushDataHandler(constraints.AllScene, wp.NewHandleFn(wp.PreCodeAndStats, 80, "wp.PreCodeAndStats")) + h.PushRender(constraints.AllScene, wp.NewHandleFn(wp.PreTemplate, 70, "wp.PreTemplate")) } func postThumb(h *wp.Handle) { diff --git a/internal/theme/twentyseventeen/twentyseventeen.go b/internal/theme/twentyseventeen/twentyseventeen.go index ffe4913..a0d003b 100644 --- a/internal/theme/twentyseventeen/twentyseventeen.go +++ b/internal/theme/twentyseventeen/twentyseventeen.go @@ -42,7 +42,10 @@ var paginate = func() plugins.PageEle { return p }() -var pipe = wp.HandlePipe(wp.ExecuteHandleFn, widget.MiddleWare(ready, wp.DataHandle)...) +var pipe = wp.HandlePipe(wp.NothingToDo, widget.MiddleWare(ready, + wp.PipeHandle(constraints.PipData, wp.PipeKey, wp.PipeDataHandle), + wp.PipeHandle(constraints.PipRender, wp.PipeKey, wp.PipeRender), +)...) func Hook(h *wp.Handle) { pipe(h) @@ -55,23 +58,24 @@ func configs(h *wp.Handle) { h.PushCacheGroupHeadScript("colorScheme-customHeader", 10, colorScheme, customHeader) components.WidgetArea(h) pushScripts(h) - h.PushRender(constraints.AllStats, wp.NewHandleFn(func(h *wp.Handle) { - h.SetData("HeaderImage", getHeaderImage(h)) - }, 10)) + h.PushRender(constraints.AllStats, wp.NewHandleFn(headerImage, 10, "headerImage")) h.SetComponentsArgs(widgets.Widget, map[string]string{ "{$before_widget}": `
`, "{$after_widget}": `
`, }) - h.PushGroupRender(constraints.AllStats, 90, wp.PreTemplate, errorsHandle) + h.PushRender(constraints.AllStats, + wp.NewHandleFn(wp.PreTemplate, 70, "wp.PreTemplate"), + wp.NewHandleFn(errorsHandle, 80, "errorsHandle"), + ) h.CommonComponents() h.Index.SetPageEle(paginate) h.Index.SetListPlugin(wp.PostsPlugins(wp.PostPlugin(postThumbnail), wp.GetListPostPlugins(conf.ListPagePlugins, wp.ListPostPlugins())...)) wp.SetComponentsArgsForMap(h, widgets.Search, "{$form}", searchForm) - h.PushRender(constraints.AllStats, wp.NewHandleFn(wp.IndexRender, 10)) - h.PushRender(constraints.Detail, wp.NewHandleFn(wp.DetailRender, 10)) - h.PushDataHandler(constraints.Detail, wp.NewHandleFn(detail, 100)) - h.PushDataHandler(constraints.AllScene, wp.NewHandleFn(index, 100)) - h.PushDataHandler(constraints.AllScene, wp.NewHandleFn(wp.PreCodeAndStats, 90)) + h.PushRender(constraints.AllStats, wp.NewHandleFn(wp.IndexRender, 10, "wp.IndexRender")) + h.PushRender(constraints.Detail, wp.NewHandleFn(wp.DetailRender, 10, "wp.DetailRender")) + h.PushDataHandler(constraints.Detail, wp.NewHandleFn(detail, 100, "detail")) + h.PushDataHandler(constraints.AllScene, wp.NewHandleFn(index, 100, "index")) + h.PushDataHandler(constraints.AllScene, wp.NewHandleFn(wp.PreCodeAndStats, 90, "wp.PreCodeAndStats")) } func ready(next wp.HandleFn[*wp.Handle], h *wp.Handle) { wp.InitThemeArgAndConfig(configs, h) @@ -156,6 +160,10 @@ func postThumbnail(h *wp.Handle, posts *models.Posts) { var header = reload.Vars(models.PostThumbnail{}) +func headerImage(h *wp.Handle) { + h.SetData("HeaderImage", getHeaderImage(h)) +} + func getHeaderImage(h *wp.Handle) (r models.PostThumbnail) { img := header.Load() if img.Path != "" { diff --git a/internal/theme/wp/pipe.go b/internal/theme/wp/pipe.go new file mode 100644 index 0000000..a7cccf2 --- /dev/null +++ b/internal/theme/wp/pipe.go @@ -0,0 +1,105 @@ +package wp + +import ( + "fmt" + "github.com/fthvgb1/wp-go/helper/slice" + "github.com/fthvgb1/wp-go/internal/cmd/reload" + "github.com/fthvgb1/wp-go/internal/pkg/constraints" +) + +type HandlePipeFn[T any] func(HandleFn[T], T) + +// HandlePipe 方便把功能写在其它包里 +func HandlePipe[T any](initial func(T), fns ...HandlePipeFn[T]) HandleFn[T] { + return slice.ReverseReduce(fns, func(next HandlePipeFn[T], f func(t T)) func(t T) { + return func(t T) { + next(f, t) + } + }, initial) +} + +func (h *Handle) PushHandler(pipScene int, scene int, fns ...HandleCall) { + if _, ok := h.handlers[pipScene]; !ok { + h.handlers[pipScene] = make(map[int][]HandleCall) + } + h.handlers[pipScene][scene] = append(h.handlers[pipScene][scene], fns...) +} + +func (h *Handle) PushRender(statsOrScene int, fns ...HandleCall) { + h.PushHandler(constraints.PipRender, statsOrScene, fns...) +} +func (h *Handle) PushDataHandler(scene int, fns ...HandleCall) { + h.PushHandler(constraints.PipData, scene, fns...) +} + +func PipeHandle(pipeScene int, keyFn func(*Handle, int) string, fn func(*Handle, map[int][]HandleCall) []HandleCall) func(HandleFn[*Handle], *Handle) { + return func(next HandleFn[*Handle], h *Handle) { + handlers := reload.SafetyMapBy("pipHandlers", keyFn(h, pipeScene), h, func(h *Handle) []HandleCall { + conf := h.handleHook[pipeScene] + calls := fn(h, h.handlers[pipeScene]) + calls = slice.FilterAndMap(calls, func(call HandleCall) (HandleCall, bool) { + ok := true + for _, hook := range conf { + call, ok = hook(call) + if !ok { + break + } + } + return call, ok + }) + slice.Sort(calls, func(i, j HandleCall) bool { + return i.Order > j.Order + }) + return calls + }) + for _, handler := range handlers { + handler.Fn(h) + if h.abort { + break + } + } + if !h.stopPipe { + next(h) + } + } +} + +func PipeKey(h *Handle, pipScene int) string { + return fmt.Sprintf("%d-%d-%d", pipScene, h.scene, h.scene) +} + +func PipeDataHandle(h *Handle, dataHandlers map[int][]HandleCall) (handlers []HandleCall) { + handlers = append(handlers, dataHandlers[h.scene]...) + handlers = append(handlers, dataHandlers[constraints.AllScene]...) + return +} + +func PipeRender(h *Handle, renders map[int][]HandleCall) (handlers []HandleCall) { + handlers = append(handlers, renders[h.Stats]...) + handlers = append(handlers, renders[h.scene]...) + handlers = append(handlers, renders[constraints.AllStats]...) + handlers = append(handlers, renders[constraints.AllScene]...) + return +} + +// DeleteHandle 写插件的时候用 +func (h *Handle) DeleteHandle(pipeScene int, name string) { + h.handleHook[pipeScene] = append(h.handleHook[pipeScene], func(call HandleCall) (HandleCall, bool) { + return call, name != call.Name + }) +} + +// ReplaceHandle 写插件的时候用 +func (h *Handle) ReplaceHandle(pipeScene int, name string, fn HandleFn[*Handle]) { + h.handleHook[pipeScene] = append(h.handleHook[pipeScene], func(call HandleCall) (HandleCall, bool) { + if name == call.Name { + call.Fn = fn + } + return call, true + }) +} + +// HookHandle 写插件的时候用 +func (h *Handle) HookHandle(pipeScene int, hook func(HandleCall) (HandleCall, bool)) { + h.handleHook[pipeScene] = append(h.handleHook[pipeScene], hook) +} diff --git a/internal/theme/wp/wp.go b/internal/theme/wp/wp.go index 0798943..2b3ecd9 100644 --- a/internal/theme/wp/wp.go +++ b/internal/theme/wp/wp.go @@ -1,7 +1,6 @@ package wp import ( - "fmt" "github.com/fthvgb1/wp-go/helper/maps" "github.com/fthvgb1/wp-go/helper/slice" str "github.com/fthvgb1/wp-go/helper/strings" @@ -30,21 +29,13 @@ type Handle struct { templ string components map[string][]Components[string] themeMods wpconfig.ThemeMods - renders map[int][]HandleCall - dataHandler map[int][]HandleCall + handlers map[int]map[int][]HandleCall + handleHook map[int][]func(HandleCall) (HandleCall, bool) err error abort bool + stopPipe bool componentsArgs map[string]any componentFilterFn map[string][]func(*Handle, string, ...any) string - handleCall []HandleCall -} - -func (h *Handle) HandleCall() []HandleCall { - return h.handleCall -} - -func (h *Handle) SetHandleCall(handleCall []HandleCall) { - h.handleCall = handleCall } type HandlePlugins map[string]HandleFn[*Handle] @@ -59,21 +50,20 @@ type Components[T any] struct { type HandleFn[T any] func(T) -type HandlePipeFn[T any] func(HandleFn[T], T) - type HandleCall struct { Fn HandleFn[*Handle] Order int + Name string } func InitThemeArgAndConfig(fn func(*Handle), h *Handle) { var inited = false hh := reload.GetAnyValBys("themeArgAndConfig", h, func(h *Handle) Handle { h.components = make(map[string][]Components[string]) - h.renders = make(map[int][]HandleCall) - h.dataHandler = make(map[int][]HandleCall) h.componentsArgs = make(map[string]any) h.componentFilterFn = make(map[string][]func(*Handle, string, ...any) string) + h.handlers = make(map[int]map[int][]HandleCall) + h.handleHook = make(map[int][]func(HandleCall) (HandleCall, bool)) h.ginH = gin.H{} fn(h) inited = true @@ -99,8 +89,8 @@ func InitThemeArgAndConfig(fn func(*Handle), h *Handle) { h.Index.postsPlugin = hh.Index.postsPlugin h.Index.pageEle = hh.Index.pageEle h.Detail.CommentRender = hh.Detail.CommentRender - h.renders = hh.renders - h.dataHandler = hh.dataHandler + h.handlers = hh.handlers + h.handleHook = hh.handleHook h.componentsArgs = hh.componentsArgs h.componentFilterFn = hh.componentFilterFn } @@ -126,6 +116,9 @@ func (h *Handle) ComponentFilterFnHook(name, s string, args ...any) string { func (h *Handle) Abort() { h.abort = true } +func (h *Handle) StopPipe() { + h.stopPipe = true +} func (h *Handle) CommonThemeMods() wpconfig.ThemeMods { return h.themeMods @@ -230,47 +223,6 @@ func (h *Handle) NewCacheComponent(name string, order int, fn func(handle *Handl return Components[string]{Fn: fn, CacheKey: name, Order: order} } -func (h *Handle) PushRender(statsOrScene int, fns ...HandleCall) { - h.renders[statsOrScene] = append(h.renders[statsOrScene], fns...) -} -func (h *Handle) PushDataHandler(Scene int, fns ...HandleCall) { - h.dataHandler[Scene] = append(h.dataHandler[Scene], fns...) -} - -func (h *Handle) PushGroupRender(statsOrScene, order int, fns ...HandleFn[*Handle]) { - var calls []HandleCall - for _, fn := range fns { - calls = append(calls, HandleCall{fn, order}) - } - h.renders[statsOrScene] = append(h.renders[statsOrScene], calls...) -} -func (h *Handle) PushGroupDataHandler(scene, order int, fns ...HandleFn[*Handle]) { - var calls []HandleCall - for _, fn := range fns { - calls = append(calls, HandleCall{fn, order}) - } - h.dataHandler[scene] = append(h.dataHandler[scene], calls...) -} - -func DataHandle(next HandleFn[*Handle], h *Handle) { - handlers := reload.SafetyMapBy("dataHandle", h.scene, h, func(h *Handle) []HandleCall { - a := h.dataHandler[h.scene] - aa, ok := h.dataHandler[constraints.AllScene] - if ok { - a = append(a, aa...) - } - slice.Sort(a, func(i, j HandleCall) bool { - return i.Order > j.Order - }) - return a - }) - for _, handler := range handlers { - handler.Fn(h) - } - h.DetermineHandleFns() - next(h) -} - func (h *Handle) AddCacheComponent(name string, fn func(*Handle) string) { h.components[name] = append(h.components[name], h.NewCacheComponent(name, 10, fn)) } @@ -311,31 +263,6 @@ func (h *Handle) GetPassword() { } } -func (h *Handle) ExecHandleFns() { - calls, ok := h.renders[h.Stats] - var fns []HandleCall - if ok { - fns = append(fns, calls...) - } - calls, ok = h.renders[h.scene] - if ok { - fns = append(fns, calls...) - } - calls, ok = h.renders[constraints.AllStats] - if ok { - fns = append(fns, calls...) - } - slice.Sort(fns, func(i, j HandleCall) bool { - return i.Order > j.Order - }) - for _, fn := range fns { - fn.Fn(h) - if h.abort { - break - } - } -} - func PreTemplate(h *Handle) { if h.templ == "" { h.templ = str.Join(h.theme, "/posts/index.gohtml") @@ -358,18 +285,16 @@ func PreCodeAndStats(h *Handle) { } } -func (h *Handle) Render() { - h.CommonComponents() - h.ExecHandleFns() -} - func (h *Handle) CommonComponents() { h.AddCacheComponent("customLogo", CalCustomLogo) h.PushCacheGroupHeadScript("siteIconAndCustomCss", 0, CalSiteIcon, CalCustomCss) - h.PushGroupRender(constraints.AllStats, 10, CalComponents) - h.PushRender(constraints.AllStats, NewHandleFn(func(h *Handle) { - h.C.HTML(h.Code, h.templ, h.ginH) - }, 0)) + h.PushRender(constraints.AllStats, NewHandleFn(CalComponents, 10, "wp.CalComponents")) + h.PushRender(constraints.AllStats, NewHandleFn(RenderTemplate, 0, "wp.RenderTemplate")) +} + +func RenderTemplate(h *Handle) { + h.C.HTML(h.Code, h.templ, h.ginH) + h.StopPipe() } func (h *Handle) PushComponents(name string, components ...Components[string]) { @@ -424,55 +349,10 @@ func CalComponents(h *Handle) { } } -func NewHandleFn(fn HandleFn[*Handle], order int) HandleCall { - return HandleCall{Fn: fn, Order: order} +func NewHandleFn(fn HandleFn[*Handle], order int, name string) HandleCall { + return HandleCall{Fn: fn, Order: order, Name: name} } -// HandlePipe 方便把功能写在其它包里 -func HandlePipe[T any](initial func(T), fns ...HandlePipeFn[T]) HandleFn[T] { - return slice.ReverseReduce(fns, func(next HandlePipeFn[T], f func(t T)) func(t T) { - return func(t T) { - next(f, t) - } - }, initial) -} +func NothingToDo(*Handle) { -func DetermineHandleFn(h *Handle) []HandleCall { - calls, ok := h.renders[h.Stats] - var fns []HandleCall - if ok { - fns = append(fns, calls...) - } - calls, ok = h.renders[h.scene] - if ok { - fns = append(fns, calls...) - } - calls, ok = h.renders[constraints.AllStats] - if ok { - fns = append(fns, calls...) - } - calls, ok = h.renders[constraints.AllScene] - if ok { - fns = append(fns, calls...) - } - slice.Sort(fns, func(i, j HandleCall) bool { - return i.Order > j.Order - }) - return fns -} - -func (h *Handle) DetermineHandleFns() { - key := fmt.Sprintf("%d-%d", h.scene, h.Stats) - h.handleCall = reload.SafetyMapBy("handleCalls", key, h, func(h *Handle) []HandleCall { - return DetermineHandleFn(h) - }) -} - -func ExecuteHandleFn(h *Handle) { - for _, fn := range h.handleCall { - fn.Fn(h) - if h.abort { - break - } - } }