归档组件化 及动态加载侧边栏

This commit is contained in:
xing 2023-03-11 23:59:00 +08:00
parent cc09668fd7
commit d211e49036
14 changed files with 223 additions and 102 deletions

View File

@ -280,3 +280,9 @@ func IndexOf[T comparable](a []T, v T) int {
} }
return -1 return -1
} }
func ForEach[T any](a []T, fn func(i int, v T)) {
for i, t := range a {
fn(i, t)
}
}

View File

@ -0,0 +1,8 @@
package components
const (
SearchFormArgs = "SearchFormArgs"
RecentPostsArgs = "RecentPostsArgs"
RecentCommentsArgs = "RecentCommentsArgs"
ArchiveArgs = "ArchiveArgs"
)

View File

@ -17,6 +17,7 @@ const (
Defaults = "default" Defaults = "default"
HeadScript = "headScript" HeadScript = "headScript"
FooterScript = "footerScript" FooterScript = "footerScript"
SidebarsWidgets = "sidebarsWidgets"
) )

View File

@ -1,20 +1,7 @@
{{define "layout/sidebar" }} {{define "layout/sidebar" }}
<div id="widget-area" class="widget-area" role="complementary"> <div id="widget-area" class="widget-area" role="complementary">
<aside id="search-2" class="widget widget_search"> {{template "common/sidebarWidget" .}}
{{if .searchConf}}
<h2 class="widget-title">{{.searchConf}}</h2>
{{end}}
<form role="search" method="get" class="search-form" action="/">
<label>
<span class="screen-reader-text">搜索:</span>
<input type="search" class="search-field" placeholder="搜索…" value="{{.search}}" name="s">
</label>
<input type="submit" class="search-submit screen-reader-text" value="搜索">
</form>
</aside>
{{template "common/recent-posts" .}}
{{template "common/recent-comments" .}}
{{template "common/archives" .}}
<aside id="categories-2" class="widget widget_categories"> <aside id="categories-2" class="widget widget_categories">
<h2 class="widget-title">分类</h2> <h2 class="widget-title">分类</h2>
<nav aria-label="分类"> <nav aria-label="分类">

View File

@ -5,9 +5,11 @@ import (
"encoding/json" "encoding/json"
"github.com/fthvgb1/wp-go/internal/pkg/config" "github.com/fthvgb1/wp-go/internal/pkg/config"
"github.com/fthvgb1/wp-go/internal/pkg/constraints" "github.com/fthvgb1/wp-go/internal/pkg/constraints"
"github.com/fthvgb1/wp-go/internal/pkg/constraints/components"
"github.com/fthvgb1/wp-go/internal/pkg/logs" "github.com/fthvgb1/wp-go/internal/pkg/logs"
"github.com/fthvgb1/wp-go/internal/plugins/wphandle" "github.com/fthvgb1/wp-go/internal/plugins/wphandle"
"github.com/fthvgb1/wp-go/internal/theme/wp" "github.com/fthvgb1/wp-go/internal/theme/wp"
"strings"
) )
const ThemeName = "twentyfifteen" const ThemeName = "twentyfifteen"
@ -37,8 +39,11 @@ func Hook(h *wp.Handle) {
} }
func dispatch(next wp.HandleFn[*wp.Handle], h *wp.Handle) { func dispatch(next wp.HandleFn[*wp.Handle], h *wp.Handle) {
h.WidgetAreaData() h.WidgetArea()
h.GetPassword() h.GetPassword()
h.PushComponentFilterFn(components.SearchFormArgs, func(h *wp.Handle, s string) string {
return strings.ReplaceAll(s, `class="search-submit"`, `class="search-submit screen-reader-text"`)
})
wphandle.RegisterPlugins(h, config.GetConfig().Plugins...) wphandle.RegisterPlugins(h, config.GetConfig().Plugins...)
h.PushCacheGroupHeadScript("CalCustomBackGround", 10, CalCustomBackGround, colorSchemeCss) h.PushCacheGroupHeadScript("CalCustomBackGround", 10, CalCustomBackGround, colorSchemeCss)

View File

@ -47,7 +47,7 @@ func Hook(h *wp.Handle) {
} }
func ready(next wp.HandleFn[*wp.Handle], h *wp.Handle) { func ready(next wp.HandleFn[*wp.Handle], h *wp.Handle) {
h.WidgetAreaData() h.WidgetArea()
h.GetPassword() h.GetPassword()
wphandle.RegisterPlugins(h, config.GetConfig().Plugins...) wphandle.RegisterPlugins(h, config.GetConfig().Plugins...)
h.PushHandleFn(constraints.AllStats, wp.NewHandleFn(calClass, 20)) h.PushHandleFn(constraints.AllStats, wp.NewHandleFn(calClass, 20))

View File

@ -0,0 +1,113 @@
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"
"github.com/fthvgb1/wp-go/internal/pkg/cache"
"github.com/fthvgb1/wp-go/internal/pkg/constraints/components"
"github.com/fthvgb1/wp-go/internal/pkg/models"
"github.com/fthvgb1/wp-go/internal/wpconfig"
"strings"
)
var archivesConfig = map[any]any{
"count": int64(0),
"dropdown": int64(0),
"title": "归档",
}
var archiveArgs = map[string]string{
"{$before_widget}": `<aside id="archives-2" class="widget widget_archive">`,
"{$after_widget}": "</aside>",
"{$before_title}": `<h2 class="widget-title">`,
"{$after_title}": "</h2>",
"{$before_sidebar}": "",
"{$after_sidebar}": "",
"{$nav}": "",
"{$navCloser}": "",
"{$title}": "",
"{$dropdown_id}": "archives-dropdown-2",
"{$dropdown_type}": "monthly",
"{$dropdown_label}": "选择月份",
}
var archiveTemplate = `{$before_widget}
{$title}
{$nav}
{$html}
{$navCloser}
{$after_widget}
`
func Archive(h *Handle) string {
args := GetComponentsArgs(h, components.ArchiveArgs, archiveArgs)
args = maps.Merge(archiveArgs, args)
conf := wpconfig.GetPHPArrayVal("widget_archives", archivesConfig, int64(2))
args["{$title}"] = str.Join(args["{$before_title}"], conf["title"].(string), args["{$after_title}"])
s := archiveTemplate
if int64(1) == conf["dropdown"].(int64) {
s = strings.ReplaceAll(s, "{$html}", archiveDropDown(h, conf, args, cache.Archives(h.C)))
} else {
s = strings.ReplaceAll(s, "{$html}", archiveUl(h, conf, args, cache.Archives(h.C)))
}
return h.ComponentFilterFnHook(components.ArchiveArgs, str.Replace(s, args))
}
var dropdownScript = `
<script>
/* <![CDATA[ */
(function() {
const dropdown = document.getElementById("archives-dropdown-2");
function onSelectChange() {
if ( dropdown.options[ dropdown.selectedIndex ].value !== '' ) {
document.location.href = this.options[ this.selectedIndex ].value;
}
}
dropdown.onchange = onSelectChange;
})();
/* ]]> */
</script>`
func archiveDropDown(h *Handle, conf map[any]any, args map[string]string, archives []models.PostArchive) string {
option := str.NewBuilder()
option.Sprintf(`<option value="">%s</option>`, args["{$dropdown_label}"])
month := strings.TrimLeft(h.Index.Param.Month, "0")
showCount := conf["count"].(int64)
for _, archive := range archives {
sel := ""
if h.Index.Param.Year == archive.Year && month == archive.Month {
sel = "selected"
}
count := ""
if showCount == int64(1) {
count = fmt.Sprintf("(%v)", archive.Posts)
}
option.Sprintf(`<option %s value="/p/date/%s/%02s" >%s年%s月 %s</option>
`, sel, archive.Year, archive.Month, archive.Year, archive.Month, count)
}
s := str.NewBuilder()
s.Sprintf(`<label class="screen-reader-text" for="%s">%s</label>
<select id="%s" name="archive-dropdown">%s</select>%s
`, args["{$dropdown_id}"], args["{$title}"], args["{$dropdown_id}"], option.String(), dropdownScript)
return s.String()
}
func archiveUl(h *Handle, conf map[any]any, args map[string]string, archives []models.PostArchive) string {
if slice.IsContained(h.CommonThemeMods().ThemeSupport.HTML5, "navigation-widgets") {
args["{$nav}"] = fmt.Sprintf(`<nav aria-label="%s">`, conf["title"].(string))
args["{$navCloser}"] = "</nav>"
}
s := str.NewBuilder()
s.WriteString(`<ul>`)
showCount := conf["count"].(int64)
for _, archive := range archives {
count := ""
if showCount == 1 {
count = fmt.Sprintf("(%v)", archive.Posts)
}
s.Sprintf(`<li><a href="/p/date/%[1]s/%[2]02s">%[1]s年%[2]s月%[3]s</a></li>`, archive.Year, archive.Month, count)
}
return s.String()
}

View File

@ -1,6 +0,0 @@
package components
const (
SearchFormArgs = "SearchFormArgs"
RecentPostsArgs = "RecentPostsArgs"
)

View File

@ -6,8 +6,8 @@ import (
"github.com/fthvgb1/wp-go/helper/slice" "github.com/fthvgb1/wp-go/helper/slice"
str "github.com/fthvgb1/wp-go/helper/strings" str "github.com/fthvgb1/wp-go/helper/strings"
"github.com/fthvgb1/wp-go/internal/pkg/cache" "github.com/fthvgb1/wp-go/internal/pkg/cache"
"github.com/fthvgb1/wp-go/internal/pkg/constraints/components"
"github.com/fthvgb1/wp-go/internal/pkg/models" "github.com/fthvgb1/wp-go/internal/pkg/models"
"github.com/fthvgb1/wp-go/internal/theme/wp/components"
"github.com/fthvgb1/wp-go/internal/wpconfig" "github.com/fthvgb1/wp-go/internal/wpconfig"
"strings" "strings"
) )
@ -57,5 +57,5 @@ func RecentComments(h *Handle) string {
</li>`, t.CommentAuthor, t.CommentId, t.CommentPostId, t.PostTitle) </li>`, t.CommentAuthor, t.CommentId, t.CommentPostId, t.PostTitle)
}) })
s := strings.ReplaceAll(recentCommentsTemplate, "{$li}", strings.Join(comments, "\n")) s := strings.ReplaceAll(recentCommentsTemplate, "{$li}", strings.Join(comments, "\n"))
return str.Replace(s, args) return h.ComponentFilterFnHook(components.RecentCommentsArgs, str.Replace(s, args))
} }

View File

@ -7,8 +7,8 @@ import (
str "github.com/fthvgb1/wp-go/helper/strings" str "github.com/fthvgb1/wp-go/helper/strings"
"github.com/fthvgb1/wp-go/internal/pkg/cache" "github.com/fthvgb1/wp-go/internal/pkg/cache"
"github.com/fthvgb1/wp-go/internal/pkg/constraints" "github.com/fthvgb1/wp-go/internal/pkg/constraints"
"github.com/fthvgb1/wp-go/internal/pkg/constraints/components"
"github.com/fthvgb1/wp-go/internal/pkg/models" "github.com/fthvgb1/wp-go/internal/pkg/models"
"github.com/fthvgb1/wp-go/internal/theme/wp/components"
"github.com/fthvgb1/wp-go/internal/wpconfig" "github.com/fthvgb1/wp-go/internal/wpconfig"
"strings" "strings"
) )
@ -70,5 +70,5 @@ func RecentPosts(h *Handle) string {
</li>`, t.Id, ariaCurrent, t.PostTitle, date) </li>`, t.Id, ariaCurrent, t.PostTitle, date)
}) })
s := strings.ReplaceAll(recentPostsTemplate, "{$li}", strings.Join(posts, "\n")) s := strings.ReplaceAll(recentPostsTemplate, "{$li}", strings.Join(posts, "\n"))
return str.Replace(s, args) return h.ComponentFilterFnHook(components.RecentPostsArgs, str.Replace(s, args))
} }

View File

@ -5,7 +5,7 @@ import (
"github.com/fthvgb1/wp-go/helper/maps" "github.com/fthvgb1/wp-go/helper/maps"
"github.com/fthvgb1/wp-go/helper/slice" "github.com/fthvgb1/wp-go/helper/slice"
str "github.com/fthvgb1/wp-go/helper/strings" str "github.com/fthvgb1/wp-go/helper/strings"
"github.com/fthvgb1/wp-go/internal/theme/wp/components" "github.com/fthvgb1/wp-go/internal/pkg/constraints/components"
"github.com/fthvgb1/wp-go/internal/wpconfig" "github.com/fthvgb1/wp-go/internal/wpconfig"
"strings" "strings"
) )
@ -17,6 +17,7 @@ var searchTemplate = `{$before_widget}
var searchArgs = map[string]string{ var searchArgs = map[string]string{
"{$before_widget}": `<aside id="search-2" class="widget widget_search">`, "{$before_widget}": `<aside id="search-2" class="widget widget_search">`,
"{$after_widget}": `</aside>`,
"{$aria_label}": "", "{$aria_label}": "",
"{$title}": "", "{$title}": "",
"{$before_title}": `<h2 class="widget-title">`, "{$before_title}": `<h2 class="widget-title">`,
@ -41,7 +42,7 @@ var xmlSearchForm = `<form role="search" {$aria_label} method="get" id="searchfo
</div> </div>
</form>` </form>`
func GetSearchForm(h *Handle) string { func SearchForm(h *Handle) string {
args := GetComponentsArgs(h, components.SearchFormArgs, searchArgs) args := GetComponentsArgs(h, components.SearchFormArgs, searchArgs)
args = maps.Merge(searchArgs, args) args = maps.Merge(searchArgs, args)
if args["{$title}"] == "" { if args["{$title}"] == "" {
@ -56,5 +57,5 @@ func GetSearchForm(h *Handle) string {
form = xmlSearchForm form = xmlSearchForm
} }
s := strings.ReplaceAll(searchTemplate, "{$form}", form) s := strings.ReplaceAll(searchTemplate, "{$form}", form)
return str.Replace(s, args) return h.ComponentFilterFnHook(components.SearchFormArgs, str.Replace(s, args))
} }

View File

@ -23,3 +23,9 @@
{{.customLogo|unescaped}} {{.customLogo|unescaped}}
{{end}} {{end}}
{{end}} {{end}}
{{define "common/sidebarWidget"}}
{{if .sidebarsWidgets}}
{{.sidebarsWidgets|unescaped}}
{{end}}
{{end}}

View File

@ -7,44 +7,25 @@ import (
"github.com/fthvgb1/wp-go/internal/wpconfig" "github.com/fthvgb1/wp-go/internal/wpconfig"
) )
func (h *Handle) WidgetAreaData() { var widgets = map[string]func(*Handle) string{
h.Archives() "search-2": SearchForm,
h.RecentPosts() "recent-posts-2": RecentPosts,
h.RecentComments() "recent-comments-2": RecentComments,
h.ginH["searchConf"] = wpconfig.GetPHPArrayVal("widget_search", "", int64(2), "title") "archives-2": Archive,
}
func (h *Handle) WidgetArea() {
v := wpconfig.GetPHPArrayVal("sidebars_widgets", []any{}, "sidebar-1")
sidebar := slice.FilterAndMap(v, func(t any) (func(*Handle) string, bool) {
widget := t.(string)
fn, ok := widgets[widget]
if ok {
return fn, true
}
return nil, false
})
h.PushHandleFn(constraints.Ok, NewHandleFn(func(h *Handle) {
h.PushGroupCacheComponentFn(constraints.SidebarsWidgets, constraints.SidebarsWidgets, 10, sidebar...)
}, 30))
h.ginH["categories"] = cache.CategoriesTags(h.C, constraints.Category) h.ginH["categories"] = cache.CategoriesTags(h.C, constraints.Category)
} }
var recentConf = map[any]any{
"number": int64(5),
"show_date": 0,
"title": "近期文章",
}
func (h *Handle) RecentPosts() {
set := wpconfig.GetPHPArrayVal[map[any]any]("widget_recent-posts", recentConf, int64(2))
h.ginH["recentPostsConfig"] = set
h.ginH["recentPosts"] = slice.Map(cache.RecentPosts(h.C, int(set["number"].(int64))), ProjectTitle)
}
var recentCommentConf = map[any]any{
"number": int64(5),
"title": "近期文章",
}
func (h *Handle) RecentComments() {
set := wpconfig.GetPHPArrayVal[map[any]any]("widget_recent-comments", recentCommentConf, int64(2))
h.ginH["recentCommentsConfig"] = set
h.ginH["recentComments"] = cache.RecentComments(h.C, int(set["number"].(int64)))
}
var archivesConfig = map[any]any{
"count": 0,
"dropdown": 0,
"title": "归档",
}
func (h *Handle) Archives() {
h.ginH["archivesConfig"] = wpconfig.GetPHPArrayVal[map[any]any]("widget_archives", archivesConfig, int64(2))
h.ginH["archives"] = cache.Archives(h.C)
}

View File

@ -16,24 +16,25 @@ import (
) )
type Handle struct { type Handle struct {
Index *IndexHandle Index *IndexHandle
Detail *DetailHandle Detail *DetailHandle
C *gin.Context C *gin.Context
theme string theme string
Session sessions.Session Session sessions.Session
ginH gin.H ginH gin.H
password string password string
scene int scene int
Code int Code int
Stats int Stats int
templ string templ string
class []string class []string
components map[string][]Components components map[string][]Components
themeMods wpconfig.ThemeMods themeMods wpconfig.ThemeMods
handleFns map[int][]HandleCall handleFns map[int][]HandleCall
err error err error
abort bool abort bool
componentsArgs map[string]any componentsArgs map[string]any
componentFilterFn map[string][]func(*Handle, string) string
} }
type HandlePlugins map[string]HandleFn[*Handle] type HandlePlugins map[string]HandleFn[*Handle]
@ -53,6 +54,23 @@ type HandleCall struct {
Order int Order int
} }
func (h *Handle) ComponentFilterFn(name string) []func(*Handle, string) string {
return h.componentFilterFn[name]
}
func (h *Handle) PushComponentFilterFn(name string, fns ...func(*Handle, string) string) {
h.componentFilterFn[name] = append(h.componentFilterFn[name], fns...)
}
func (h *Handle) ComponentFilterFnHook(name, s string) string {
calls, ok := h.componentFilterFn[name]
if ok {
return slice.Reduce(calls, func(fn func(*Handle, string) string, r string) string {
return fn(h, r)
}, s)
}
return s
}
func (h *Handle) Abort() { func (h *Handle) Abort() {
h.abort = true h.abort = true
} }
@ -151,16 +169,17 @@ func NewHandle(c *gin.Context, scene int, theme string) *Handle {
mods, err := wpconfig.GetThemeMods(theme) mods, err := wpconfig.GetThemeMods(theme)
logs.ErrPrintln(err, "获取mods失败") logs.ErrPrintln(err, "获取mods失败")
return &Handle{ return &Handle{
C: c, C: c,
theme: theme, theme: theme,
Session: sessions.Default(c), Session: sessions.Default(c),
ginH: gin.H{}, ginH: gin.H{},
scene: scene, scene: scene,
Stats: constraints.Ok, Stats: constraints.Ok,
themeMods: mods, themeMods: mods,
components: make(map[string][]Components), components: make(map[string][]Components),
handleFns: make(map[int][]HandleCall), handleFns: make(map[int][]HandleCall),
componentsArgs: make(map[string]any), componentsArgs: make(map[string]any),
componentFilterFn: make(map[string][]func(*Handle, string) string),
} }
} }
@ -197,7 +216,7 @@ func (h *Handle) PushGroupHeadScript(order int, str ...string) {
h.PushGroupComponents(constraints.HeadScript, order, str...) h.PushGroupComponents(constraints.HeadScript, order, str...)
} }
func (h *Handle) PushCacheGroupHeadScript(key string, order int, fns ...func(*Handle) string) { func (h *Handle) PushCacheGroupHeadScript(key string, order int, fns ...func(*Handle) string) {
h.PushGroupCacheScript(constraints.HeadScript, key, order, fns...) h.PushGroupCacheComponentFn(constraints.HeadScript, key, order, fns...)
} }
func (h *Handle) PushFooterScript(fn ...Components) { func (h *Handle) PushFooterScript(fn ...Components) {
@ -213,9 +232,9 @@ func (h *Handle) componentKey(name string) string {
} }
func (h *Handle) PushCacheGroupFooterScript(key string, order int, fns ...func(*Handle) string) { func (h *Handle) PushCacheGroupFooterScript(key string, order int, fns ...func(*Handle) string) {
h.PushGroupCacheScript(constraints.FooterScript, key, order, fns...) h.PushGroupCacheComponentFn(constraints.FooterScript, key, order, fns...)
} }
func (h *Handle) PushGroupCacheScript(name, key string, order int, fns ...func(*Handle) string) { func (h *Handle) PushGroupCacheComponentFn(name, key string, order int, fns ...func(*Handle) string) {
v := reload.GetStrBy(key, "\n", h, fns...) v := reload.GetStrBy(key, "\n", h, fns...)
h.PushGroupComponents(name, order, v) h.PushGroupComponents(name, order, v)
} }