Compare commits

...

2 Commits

Author SHA1 Message Date
ca94295eb7 其它操作 加隐藏登录插件 及优化完善 2023-03-17 00:45:04 +08:00
aaa1f3c937 tree 测试 2023-03-16 12:28:53 +08:00
18 changed files with 589 additions and 60 deletions

View File

@ -23,10 +23,20 @@
|-----|--------------------------------------------| |-----|--------------------------------------------|
| 列表页 | 首页/搜索/归档/分类/标签/作者 分页列表 | | 列表页 | 首页/搜索/归档/分类/标签/作者 分页列表 |
| 详情页 | 显示内容、评论并可以添加评论(转发的php处理需要配置php版的添加评论的url) | | 详情页 | 显示内容、评论并可以添加评论(转发的php处理需要配置php版的添加评论的url) |
| 侧边栏 | 目前固定 近期文章、近期评论、规档、分类、条目/评论feed | | 侧边栏 | 目前支持旧版小工具的 近期文章、近期评论、规档、分类、其它操作 显示及设置 |
#### 后台设置支持程度 #### 后台设置支持程度
- 仪表盘
- 外观
- 小工具
- 搜索
- 规档
- 近期文章
- 近期评论
- 分类
- 其它操作
- 设置- - 设置-
- 常规 - 常规
- 站点标题 - 站点标题
@ -55,7 +65,7 @@
| 列表页文章数据插件 | 整个程序表现的插件 | | 列表页文章数据插件 | 整个程序表现的插件 |
|----------------------|--------------------------------------| |----------------------|--------------------------------------|
| passwordProject 密码保护 | enlighter 代码高亮(需要在后台安装enlighterjs插件) | | passwordProject 密码保护 | enlighter 代码高亮(需要在后台安装enlighterjs插件) |
| digest 自动生成指定长度的摘要 | | | digest 自动生成指定长度的摘要 | hiddenLogin 隐藏登录入口 |
#### 其它 #### 其它

View File

@ -14,6 +14,20 @@ func (n *Node[T, K]) GetChildren() []T {
}) })
} }
func (n *Node[T, K]) Posterity() (r []T) {
n.posterity(&r)
return r
}
func (n *Node[T, K]) posterity(a *[]T) {
for _, n2 := range *n.Children {
*a = append(*a, n2.Data)
if len(*n2.Children) > 0 {
n2.posterity(a)
}
}
}
func (n *Node[T, K]) ChildrenByOrder(fn func(T, T) bool) []T { func (n *Node[T, K]) ChildrenByOrder(fn func(T, T) bool) []T {
a := slice.Map(*n.Children, func(t Node[T, K]) T { a := slice.Map(*n.Children, func(t Node[T, K]) T {
return t.Data return t.Data

398
helper/tree/tree_test.go Normal file
View File

@ -0,0 +1,398 @@
package tree
import (
"fmt"
"github.com/fthvgb1/wp-go/helper/slice"
"reflect"
"testing"
)
type xx struct {
id int
pid int
}
var ss []xx
func init() {
ss = []xx{
{1, 0},
{2, 0},
{3, 0},
{4, 1},
{5, 1},
{6, 2},
{7, 3},
{8, 4},
{9, 5},
{10, 2},
}
}
func ffn(x xx) (child, parent int) {
return x.id, x.pid
}
func TestAncestor(t *testing.T) {
type args[K comparable, T any] struct {
root map[K]*Node[T, K]
top K
child *Node[T, K]
}
type testCase[K comparable, T any] struct {
name string
args args[K, T]
want *Node[T, K]
}
r := Roots(ss, 0, ffn)
tests := []testCase[int, xx]{
{
name: "t1",
args: args[int, xx]{
root: r,
top: 0,
child: &Node[xx, int]{
Data: xx{9, 5},
Parent: 5,
},
},
want: &Node[xx, int]{
Data: xx{
id: 1,
pid: 0,
},
Children: &[]Node[xx, int]{
{
Data: xx{4, 1},
Children: &[]Node[xx, int]{
{
Data: xx{8, 4},
Parent: 4,
},
},
},
{
Data: xx{5, 1},
Children: &[]Node[xx, int]{
{
Data: xx{9, 5},
Parent: 5,
},
},
},
},
},
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
if got := Ancestor(tt.args.root, tt.args.top, tt.args.child); !reflect.DeepEqual(*got, *tt.want) {
t.Errorf("Ancestor() = %v, want %v", got, tt.want)
}
})
}
}
func TestNode_ChildrenByOrder(t *testing.T) {
type args[T any] struct {
fn func(T, T) bool
}
type testCase[T any, K comparable] struct {
name string
n Node[T, K]
args args[T]
want []T
}
tests := []testCase[xx, int]{
{
name: "t1",
n: *root(ss, 0, ffn)[2],
args: args[xx]{
fn: func(x xx, x2 xx) bool {
return x.id < x2.id
},
},
want: []xx{{6, 2}, {10, 2}},
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
if got := tt.n.ChildrenByOrder(tt.args.fn); !reflect.DeepEqual(got, tt.want) {
t.Errorf("ChildrenByOrder() = %v, want %v", got, tt.want)
}
})
}
}
func TestNode_GetChildren(t *testing.T) {
type testCase[T any, K comparable] struct {
name string
n Node[T, K]
want []T
}
tests := []testCase[xx, int]{
{
name: "t1",
n: *root(ss, 0, ffn)[2],
want: []xx{{6, 2}, {10, 2}},
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
if got := tt.n.GetChildren(); !reflect.DeepEqual(got, tt.want) {
t.Errorf("GetChildren() = %v, want %v", got, tt.want)
}
})
}
}
func TestNode_Loop(t *testing.T) {
type args[T any] struct {
fn func(T, int)
}
type testCase[T any, K comparable] struct {
name string
n Node[T, K]
args args[T]
}
tests := []testCase[xx, int]{
{
name: "t1",
n: *Root(ss, 0, ffn),
args: args[xx]{
fn: func(x xx, i int) {
fmt.Println(x, i)
},
},
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
tt.n.Loop(tt.args.fn)
})
}
}
func TestNode_OrderByLoop(t *testing.T) {
type args[T any] struct {
fn func(T, int)
orderBy func(T, T) bool
}
type testCase[T any, K comparable] struct {
name string
n Node[T, K]
args args[T]
}
tests := []testCase[xx, int]{
{
name: "",
n: *Root(ss, 0, ffn),
args: args[xx]{
fn: func(x xx, i int) {
fmt.Println(x)
},
orderBy: func(x xx, x2 xx) bool {
return x.id > x2.id
},
},
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
tt.n.OrderByLoop(tt.args.fn, tt.args.orderBy)
})
}
}
func TestNode_Posterity(t *testing.T) {
type testCase[T any, K comparable] struct {
name string
n Node[T, K]
wantR []T
}
tests := []testCase[xx, int]{
{
name: "t1",
n: *Root(ss, 0, ffn),
wantR: ss,
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
gotR := tt.n.Posterity()
fn := func(i, j xx) bool {
if i.id < j.id {
return true
}
if i.pid < j.pid {
return true
}
return false
}
slice.Sort(gotR, fn)
slice.Sort(tt.wantR, fn)
if !reflect.DeepEqual(gotR, tt.wantR) {
t.Errorf("Posterity() = %v, want %v", gotR, tt.wantR)
}
})
}
}
func TestNode_loop(t *testing.T) {
type args[T any] struct {
fn func(T, int)
deep int
}
type testCase[T any, K comparable] struct {
name string
n Node[T, K]
args args[T]
}
tests := []testCase[xx, int]{
{
name: "t1",
n: *Root(ss, 0, ffn),
args: args[xx]{fn: func(x xx, i int) {
fmt.Println(x)
}},
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
tt.n.loop(tt.args.fn, tt.args.deep)
})
}
}
func TestNode_orderByLoop(t *testing.T) {
type args[T any] struct {
fn func(T, int)
orderBy func(T, T) bool
deep int
}
type testCase[T any, K comparable] struct {
name string
n Node[T, K]
args args[T]
}
tests := []testCase[xx, int]{
{
name: "t1",
n: *Root(ss, 0, ffn),
args: args[xx]{fn: func(x xx, i int) {
fmt.Println(x)
}, orderBy: func(x xx, x2 xx) bool {
return x.id > x2.id
}},
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
tt.n.orderByLoop(tt.args.fn, tt.args.orderBy, tt.args.deep)
})
}
}
func TestNode_posterity(t *testing.T) {
type args[T any] struct {
a *[]T
}
type testCase[T any, K comparable] struct {
name string
n Node[T, K]
args args[T]
}
tests := []testCase[xx, int]{
{
name: "t1",
n: *Root(ss, 0, ffn),
args: args[xx]{a: new([]xx)},
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
tt.n.posterity(tt.args.a)
})
}
}
func TestRoot(t *testing.T) {
type args[T any, K comparable] struct {
a []T
top K
fn func(T) (child, parent K)
}
type testCase[T any, K comparable] struct {
name string
args args[T, K]
want *Node[T, K]
}
tests := []testCase[xx, int]{
{
name: "t1",
args: args[xx, int]{
a: ss,
top: 0,
fn: ffn,
},
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
if got := Root(tt.args.a, tt.args.top, tt.args.fn); !reflect.DeepEqual(got, tt.want) {
t.Errorf("Root() = %v, want %v", got, tt.want)
}
})
}
}
func TestRoots(t *testing.T) {
type args[T any, K comparable] struct {
a []T
top K
fn func(T) (child, parent K)
}
type testCase[T any, K comparable] struct {
name string
args args[T, K]
want map[K]*Node[T, K]
}
tests := []testCase[xx, int]{
{
name: "t1",
args: args[xx, int]{ss, 0, ffn},
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
if got := Roots(tt.args.a, tt.args.top, tt.args.fn); !reflect.DeepEqual(got, tt.want) {
t.Errorf("Roots() = %v, want %v", got, tt.want)
}
})
}
}
func Test_root(t *testing.T) {
type args[T any, K comparable] struct {
a []T
top K
fn func(T) (child, parent K)
}
type testCase[T any, K comparable] struct {
name string
args args[T, K]
want map[K]*Node[T, K]
}
tests := []testCase[xx, int]{
{
name: "t1",
args: args[xx, int]{ss, 0, ffn},
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
if got := root(tt.args.a, tt.args.top, tt.args.fn); !reflect.DeepEqual(got, tt.want) {
t.Errorf("root() = %v, want %v", got, tt.want)
}
})
}
}

View File

@ -1,9 +1,10 @@
package widgets package widgets
const ( const (
SearchFormArgs = "SearchFormArgs" Search = "search"
RecentPostsArgs = "RecentPostsArgs" RecentPosts = "recent-posts"
RecentCommentsArgs = "RecentCommentsArgs" RecentComments = "recent-comments"
ArchiveArgs = "ArchiveArgs" Archive = "archives"
Categories = "Categories" Categories = "categories"
Meta = "meta"
) )

View File

@ -3,11 +3,13 @@ package wphandle
import ( import (
"github.com/fthvgb1/wp-go/helper/maps" "github.com/fthvgb1/wp-go/helper/maps"
"github.com/fthvgb1/wp-go/internal/plugins/wphandle/enlightjs" "github.com/fthvgb1/wp-go/internal/plugins/wphandle/enlightjs"
"github.com/fthvgb1/wp-go/internal/plugins/wphandle/hiddenlogin"
"github.com/fthvgb1/wp-go/internal/theme/wp" "github.com/fthvgb1/wp-go/internal/theme/wp"
) )
var plugins = wp.HandlePlugins{ var plugins = wp.HandlePlugins{
"enlightjs": enlightjs.EnlighterJS, "enlightjs": enlightjs.EnlighterJS,
"hiddenLogin": hiddenlogin.HiddenLogin,
} }
func Plugins() wp.HandlePlugins { func Plugins() wp.HandlePlugins {

View File

@ -0,0 +1,17 @@
package hiddenlogin
import (
str "github.com/fthvgb1/wp-go/helper/strings"
"github.com/fthvgb1/wp-go/internal/pkg/constraints/widgets"
"github.com/fthvgb1/wp-go/internal/theme/wp"
)
func HiddenLogin(h *wp.Handle) {
h.PushComponentFilterFn(widgets.Meta, func(h *wp.Handle, s string) string {
return str.Replace(s, map[string]string{
`<li><a href="/wp-login.php">登录</a></li>`: "",
`<li><a href="/feed">登录</a></li>`: "",
`<li><a href="/comments/feed">登录</a></li>`: "",
})
})
}

View File

@ -1,14 +1,5 @@
{{define "layout/sidebar" }} {{define "layout/sidebar" }}
<div id="widget-area" class="widget-area" role="complementary"> <div id="widget-area" class="widget-area" role="complementary">
{{template "common/sidebarWidget" .}} {{template "common/sidebarWidget" .}}
<aside id="meta-2" class="widget widget_meta"><h2 class="widget-title">其他操作</h2>
<nav aria-label="其他操作">
<ul>
<li><a href="/feed">条目feed</a></li>
<li><a href="/comments/feed">评论feed</a></li>
</ul>
</nav>
</aside>
</div> </div>
{{end}} {{end}}

View File

@ -43,7 +43,7 @@ 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) {
components.WidgetArea(h) components.WidgetArea(h)
h.GetPassword() h.GetPassword()
h.PushComponentFilterFn(widgets.SearchFormArgs, func(h *wp.Handle, s string) string { h.PushComponentFilterFn(widgets.Search, func(h *wp.Handle, s string) string {
return strings.ReplaceAll(s, `class="search-submit"`, `class="search-submit screen-reader-text"`) 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...)

View File

@ -1,25 +1,3 @@
{{define "layout/sidebar" }} {{define "layout/sidebar" }}
{{template "common/sidebarWidget" .}} {{template "common/sidebarWidget" .}}
<section id="categories-2" class="widget widget_categories">
<h2 class="widget-title">分类</h2>
<nav aria-label="分类">
<ul>
{{range $k,$v := .categories}}
<li class="cat-item cat-item-{{$v.Terms.TermId}}">
<a href="/p/category/{{$v.Name}}">{{$v.Name}}</a>
</li>
{{end}}
</ul>
</nav>
</section>
<section id="meta-2" class="widget widget_meta">
<h2 class="widget-title">其他操作</h2>
<nav aria-label="其他操作">
<ul>
<li><a href="/feed">条目feed</a></li>
<li><a href="/comments/feed">评论feed</a></li>
</ul>
</nav>
</section>
{{end}} {{end}}

View File

@ -10,6 +10,7 @@ import (
"github.com/fthvgb1/wp-go/internal/cmd/reload" "github.com/fthvgb1/wp-go/internal/cmd/reload"
"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/widgets"
"github.com/fthvgb1/wp-go/internal/pkg/logs" "github.com/fthvgb1/wp-go/internal/pkg/logs"
"github.com/fthvgb1/wp-go/internal/pkg/models" "github.com/fthvgb1/wp-go/internal/pkg/models"
"github.com/fthvgb1/wp-go/internal/plugins" "github.com/fthvgb1/wp-go/internal/plugins"
@ -61,9 +62,29 @@ func ready(next wp.HandleFn[*wp.Handle], h *wp.Handle) {
pushScripts(h) pushScripts(h)
h.SetData("HeaderImage", getHeaderImage(h)) h.SetData("HeaderImage", getHeaderImage(h))
h.SetData("scene", h.Scene()) h.SetData("scene", h.Scene())
for _, s := range []string{widgets.Meta, widgets.Categories, widgets.Archive, widgets.Search, widgets.RecentComments, widgets.RecentPosts} {
ss := strings.ReplaceAll(s, "-", "_")
if s == widgets.RecentPosts {
ss = "recent_entries"
}
wp.SetComponentsArgsForMap(h, s, "{$before_widget}", fmt.Sprintf(`<section id="%s-2" class="widget widget_%s">`, s, ss))
wp.SetComponentsArgsForMap(h, s, "{$after_widget}", "</section>")
}
wp.SetComponentsArgsForMap(h, widgets.Search, "{$form}", searchForm)
next(h) next(h)
} }
var searchForm = `<form role="search" method="get" class="search-form" action="/">
<label for="search-form-1">
<span class="screen-reader-text">{$label}</span>
</label>
<input type="search" id="search-form-1" class="search-field" placeholder="{$placeholder}…" value="{$value}" name="s">
<button type="submit" class="search-submit">
<svg class="icon icon-search" aria-hidden="true" role="img"> <use href="#icon-search" xlink:href="#icon-search"></use> </svg>
<span class="screen-reader-text">{$button}</span>
</button>
</form>`
func dispatch(next wp.HandleFn[*wp.Handle], h *wp.Handle) { func dispatch(next wp.HandleFn[*wp.Handle], h *wp.Handle) {
switch h.Scene() { switch h.Scene() {
case constraints.Detail: case constraints.Detail:

View File

@ -36,6 +36,9 @@ func (h *Handle) BodyClass(class ...string) string {
case constraints.Category, constraints.Tag: case constraints.Category, constraints.Tag:
class = append(class, "archive", "category") class = append(class, "archive", "category")
cat := h.Index.Param.Category cat := h.Index.Param.Category
if cat == "" {
break
}
_, cate := slice.SearchFirst(cache.CategoriesTags(h.C, h.scene), func(my models.TermsMy) bool { _, cate := slice.SearchFirst(cache.CategoriesTags(h.C, h.scene), func(my models.TermsMy) bool {
return my.Name == cat return my.Name == cat
}) })

View File

@ -49,17 +49,20 @@ var archiveTemplate = `{$before_widget}
` `
func Archive(h *wp.Handle) string { func Archive(h *wp.Handle) string {
args := wp.GetComponentsArgs(h, widgets.ArchiveArgs, archiveArgs.Load()) args := wp.GetComponentsArgs(h, widgets.Archive, archiveArgs.Load())
args = maps.FilterZeroMerge(archiveArgs.Load(), args) args = maps.FilterZeroMerge(archiveArgs.Load(), args)
conf := wpconfig.GetPHPArrayVal("widget_archives", archivesConfig.Load(), int64(2)) conf := wpconfig.GetPHPArrayVal("widget_archives", archivesConfig.Load(), int64(2))
args["{$title}"] = str.Join(args["{$before_title}"], conf["title"].(string), args["{$after_title}"]) args["{$title}"] = str.Join(args["{$before_title}"], conf["title"].(string), args["{$after_title}"])
if id, ok := args["{$id}"]; ok && id != "" {
args["{$before_widget}"] = strings.ReplaceAll(args["{$before_widget}"], "2", args["{$id}"])
}
s := archiveTemplate s := archiveTemplate
if int64(1) == conf["dropdown"].(int64) { if int64(1) == conf["dropdown"].(int64) {
s = strings.ReplaceAll(s, "{$html}", archiveDropDown(h, conf, args, cache.Archives(h.C))) s = strings.ReplaceAll(s, "{$html}", archiveDropDown(h, conf, args, cache.Archives(h.C)))
} else { } else {
s = strings.ReplaceAll(s, "{$html}", archiveUl(h, conf, args, cache.Archives(h.C))) s = strings.ReplaceAll(s, "{$html}", archiveUl(h, conf, args, cache.Archives(h.C)))
} }
return h.ComponentFilterFnHook(widgets.ArchiveArgs, str.Replace(s, args)) return h.ComponentFilterFnHook(widgets.Archive, str.Replace(s, args))
} }
var dropdownScript = ` var dropdownScript = `

View File

@ -36,7 +36,7 @@ var categoryConfig = func() safety.Var[map[any]any] {
"{$class}": "postform", "{$class}": "postform",
"{$show_option_none}": "选择分类", "{$show_option_none}": "选择分类",
"{$name}": "cat", "{$name}": "cat",
"{$id}": "cat", "{$selectId}": "cat",
"{$required}": "", "{$required}": "",
"{$nav}": "", "{$nav}": "",
"{$navCloser}": "", "{$navCloser}": "",
@ -64,6 +64,9 @@ func Category(h *wp.Handle) string {
args["{$title}"] = str.Join(args["{$before_title}"], conf["title"].(string), args["{$after_title}"]) args["{$title}"] = str.Join(args["{$before_title}"], conf["title"].(string), args["{$after_title}"])
t := categoryTemplate t := categoryTemplate
dropdown := conf["dropdown"].(int64) dropdown := conf["dropdown"].(int64)
if id, ok := args["{$id}"]; ok && id != "" {
args["{$before_widget}"] = strings.ReplaceAll(args["{$before_widget}"], "2", args["{$id}"])
}
categories := cache.CategoriesTags(h.C, constraints.Category) categories := cache.CategoriesTags(h.C, constraints.Category)
if dropdown == 1 { if dropdown == 1 {
t = strings.ReplaceAll(t, "{$html}", categoryDropdown(h, args, conf, categories)) t = strings.ReplaceAll(t, "{$html}", categoryDropdown(h, args, conf, categories))
@ -71,7 +74,7 @@ func Category(h *wp.Handle) string {
} else { } else {
t = strings.ReplaceAll(t, "{$html}", categoryUL(h, args, conf, categories)) t = strings.ReplaceAll(t, "{$html}", categoryUL(h, args, conf, categories))
} }
return str.Replace(t, args) return h.ComponentFilterFnHook(widgets.Categories, str.Replace(t, args))
} }
func categoryUL(h *wp.Handle, args map[string]string, conf map[any]any, categories []models.TermsMy) string { func categoryUL(h *wp.Handle, args map[string]string, conf map[any]any, categories []models.TermsMy) string {
@ -173,10 +176,10 @@ func categoryDropdown(h *wp.Handle, args map[string]string, conf map[any]any, ca
s.WriteString(`<form action="/" method="get"> s.WriteString(`<form action="/" method="get">
`) `)
s.Sprintf(` <label class="screen-reader-text" for="%s">%s</label> s.Sprintf(` <label class="screen-reader-text" for="%s">%s</label>
`, args["{$id}"], args["{$title}"]) `, args["{$selectId}"], args["{$title}"])
if len(categories) > 0 { if len(categories) > 0 {
s.Sprintf(` <select %s name="%s" id="%s" class="%s"> s.Sprintf(` <select %s name="%s" id="%s" class="%s">
`, args["{$required}"], args["{$name}"], args["{$id}"], args["{$class}"]) `, args["{$required}"], args["{$name}"], args["{$selectId}"], args["{$class}"])
s.Sprintf(` <option value="%[1]s">%[1]s</option> s.Sprintf(` <option value="%[1]s">%[1]s</option>
`, args["{$show_option_none}"]) `, args["{$show_option_none}"])
currentCategory := "" currentCategory := ""
@ -218,7 +221,7 @@ func categoryDropdown(h *wp.Handle, args map[string]string, conf map[any]any, ca
} }
s.Sprintf(`<script%s> s.Sprintf(`<script%s>
`, attr) `, attr)
s.Sprintf(categoryDropdownJs, args["{$id}"]) s.Sprintf(categoryDropdownJs, args["{$selectId}"])
s.WriteString("</script>\n") s.WriteString("</script>\n")
return s.String() return s.String()
} }

View File

@ -0,0 +1,64 @@
package widget
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/constraints/widgets"
"github.com/fthvgb1/wp-go/internal/theme/wp"
"github.com/fthvgb1/wp-go/internal/wpconfig"
"github.com/fthvgb1/wp-go/safety"
"strings"
)
var metaTemplate = `{$before_widget}
{$h2title}
{$nav}
<ul>
{$li}
</ul>
{$navCloser}
{$after_widget}`
var metaArgs = func() safety.Var[map[string]string] {
v := safety.Var[map[string]string]{}
v.Store(map[string]string{
"{$before_widget}": `<aside id="meta-2" class="widget widget_meta">`,
"{$after_widget}": `</aside>`,
"{$aria_label}": "",
"{$title}": "",
"": "",
"{$before_title}": `<h2 class="widget-title">`,
"{$after_title}": `</h2>`,
})
return v
}()
func Meta(h *wp.Handle) string {
args := wp.GetComponentsArgs(h, widgets.Meta, metaArgs.Load())
args = maps.FilterZeroMerge(metaArgs.Load(), args)
args["{$title}"] = wpconfig.GetPHPArrayVal("widget_meta", "其它操作", int64(2), "title")
if id, ok := args["{$id}"]; ok && id != "" {
args["{$before_widget}"] = strings.ReplaceAll(args["{$before_widget}"], "2", args["{$id}"])
}
if args["{$title}"] == "" {
args["{$title}"] = "其他操作"
}
if args["{$title}"] != "" {
args["{$h2title}"] = str.Join(args["{$before_title}"], args["{$title}"], args["{$after_title}"])
}
if slice.IsContained(h.CommonThemeMods().ThemeSupport.HTML5, "navigation-widgets") {
args["{$nav}"] = fmt.Sprintf(`<nav aria-label="%s">`, args["{$title}"])
args["{$navCloser}"] = "</nav>"
}
ss := str.NewBuilder()
if str.ToInteger(wpconfig.GetOption("users_can_register"), 0) > 0 {
ss.Sprintf(`<li><a href="/wp-login.php?action=register">注册</li>`)
}
ss.Sprintf(`<li><a href="%s">登录</a></li>`, "/wp-login.php")
ss.Sprintf(`<li><a href="%s">条目feed</a></li>`, "/feed")
ss.Sprintf(`<li><a href="%s">评论feed</a></li>`, "/comments/feed")
s := strings.ReplaceAll(metaTemplate, "{$li}", ss.String())
return h.ComponentFilterFnHook(widgets.Meta, str.Replace(s, args))
}

View File

@ -48,11 +48,14 @@ var recentCommentsTemplate = `{$before_widget}
` `
func RecentComments(h *wp.Handle) string { func RecentComments(h *wp.Handle) string {
args := wp.GetComponentsArgs(h, widgets.RecentCommentsArgs, recentCommentsArgs.Load()) args := wp.GetComponentsArgs(h, widgets.RecentComments, recentCommentsArgs.Load())
args = maps.FilterZeroMerge(recentCommentsArgs.Load(), args) args = maps.FilterZeroMerge(recentCommentsArgs.Load(), args)
conf := wpconfig.GetPHPArrayVal("widget_recent-comments", recentCommentConf.Load(), int64(2)) conf := wpconfig.GetPHPArrayVal("widget_recent-comments", recentCommentConf.Load(), int64(2))
conf = maps.FilterZeroMerge(recentCommentConf.Load(), conf) conf = maps.FilterZeroMerge(recentCommentConf.Load(), conf)
args["{$title}"] = str.Join(args["{$before_title}"], conf["title"].(string), args["{$after_title}"]) args["{$title}"] = str.Join(args["{$before_title}"], conf["title"].(string), args["{$after_title}"])
if id, ok := args["{$id}"]; ok && id != "" {
args["{$before_widget}"] = strings.ReplaceAll(args["{$before_widget}"], "2", args["{$id}"])
}
if slice.IsContained(h.CommonThemeMods().ThemeSupport.HTML5, "navigation-widgets") { if slice.IsContained(h.CommonThemeMods().ThemeSupport.HTML5, "navigation-widgets") {
args["{$nav}"] = fmt.Sprintf(`<nav aria-label="%s">`, conf["title"]) args["{$nav}"] = fmt.Sprintf(`<nav aria-label="%s">`, conf["title"])
args["{$navCloser}"] = "</nav>" args["{$navCloser}"] = "</nav>"
@ -65,5 +68,5 @@ func RecentComments(h *wp.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 h.ComponentFilterFnHook(widgets.RecentCommentsArgs, str.Replace(s, args)) return h.ComponentFilterFnHook(widgets.RecentComments, str.Replace(s, args))
} }

View File

@ -50,10 +50,13 @@ var recentConf = func() safety.Var[map[any]any] {
}() }()
func RecentPosts(h *wp.Handle) string { func RecentPosts(h *wp.Handle) string {
args := wp.GetComponentsArgs(h, widgets.RecentPostsArgs, recentPostsArgs.Load()) args := wp.GetComponentsArgs(h, widgets.RecentPosts, recentPostsArgs.Load())
args = maps.FilterZeroMerge(recentPostsArgs.Load(), args) args = maps.FilterZeroMerge(recentPostsArgs.Load(), args)
conf := wpconfig.GetPHPArrayVal[map[any]any]("widget_recent-posts", recentConf.Load(), int64(2)) conf := wpconfig.GetPHPArrayVal[map[any]any]("widget_recent-posts", recentConf.Load(), int64(2))
conf = maps.FilterZeroMerge(recentConf.Load(), conf) conf = maps.FilterZeroMerge(recentConf.Load(), conf)
if id, ok := args["{$id}"]; ok && id != "" {
args["{$before_widget}"] = strings.ReplaceAll(args["{$before_widget}"], "2", args["{$id}"])
}
args["{$title}"] = str.Join(args["{$before_title}"], conf["title"].(string), args["{$after_title}"]) args["{$title}"] = str.Join(args["{$before_title}"], conf["title"].(string), args["{$after_title}"])
if slice.IsContained(h.CommonThemeMods().ThemeSupport.HTML5, "navigation-widgets") { if slice.IsContained(h.CommonThemeMods().ThemeSupport.HTML5, "navigation-widgets") {
args["{$nav}"] = fmt.Sprintf(`<nav aria-label="%s">`, conf["title"]) args["{$nav}"] = fmt.Sprintf(`<nav aria-label="%s">`, conf["title"])
@ -79,5 +82,5 @@ func RecentPosts(h *wp.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 h.ComponentFilterFnHook(widgets.RecentPostsArgs, str.Replace(s, args)) return h.ComponentFilterFnHook(widgets.RecentPosts, str.Replace(s, args))
} }

View File

@ -21,12 +21,14 @@ var searchTemplate = `{$before_widget}
var searchArgs = func() safety.Var[map[string]string] { var searchArgs = func() safety.Var[map[string]string] {
v := safety.Var[map[string]string]{} v := safety.Var[map[string]string]{}
v.Store(map[string]string{ v.Store(map[string]string{
"{$id}": "2",
"{$before_widget}": `<aside id="search-2" class="widget widget_search">`, "{$before_widget}": `<aside id="search-2" class="widget widget_search">`,
"{$after_widget}": `</aside>`, "{$after_widget}": `</aside>`,
"{$aria_label}": "", "{$aria_label}": "",
"{$title}": "", "{$title}": "",
"{$before_title}": `<h2 class="widget-title">`, "{$before_title}": `<h2 class="widget-title">`,
"{$after_title}": `</h2>`, "{$after_title}": `</h2>`,
"{$form}": "",
"{$button}": "搜索", "{$button}": "搜索",
"{$placeholder}": "搜索&hellip;", "{$placeholder}": "搜索&hellip;",
"{$label}": "搜索:", "{$label}": "搜索:",
@ -50,11 +52,14 @@ var xmlSearchForm = `<form role="search" {$aria_label} method="get" id="searchfo
</form>` </form>`
func SearchForm(h *wp.Handle) string { func SearchForm(h *wp.Handle) string {
args := wp.GetComponentsArgs(h, widgets.SearchFormArgs, searchArgs.Load()) args := wp.GetComponentsArgs(h, widgets.Search, searchArgs.Load())
args = maps.FilterZeroMerge(searchArgs.Load(), args) args = maps.FilterZeroMerge(searchArgs.Load(), args)
if args["{$title}"] == "" { if args["{$title}"] == "" {
args["{$title}"] = wpconfig.GetPHPArrayVal("widget_search", "", int64(2), "title") args["{$title}"] = wpconfig.GetPHPArrayVal("widget_search", "", int64(2), "title")
} }
if id, ok := args["{$id}"]; ok && id != "" {
args["{$before_widget}"] = strings.ReplaceAll(args["{$before_widget}"], "2", args["{$id}"])
}
if args["{$title}"] != "" { if args["{$title}"] != "" {
args["{$title}"] = str.Join(args["{$before_title}"], args["{$title}"], args["{$after_title}"]) args["{$title}"] = str.Join(args["{$before_title}"], args["{$title}"], args["{$after_title}"])
} }
@ -63,9 +68,14 @@ func SearchForm(h *wp.Handle) string {
args["{$value}"] = html.SpecialChars(h.Index.Param.Search) args["{$value}"] = html.SpecialChars(h.Index.Param.Search)
} }
form := html5SearchForm form := html5SearchForm
if !slice.IsContained(h.CommonThemeMods().ThemeSupport.HTML5, "search-form") { if args["{$form}"] != "" {
form = args["{$form}"]
delete(args, "{$form}")
}
if !slice.IsContained(h.CommonThemeMods().ThemeSupport.HTML5, "navigation-widgets") {
form = xmlSearchForm form = xmlSearchForm
} }
s := strings.ReplaceAll(searchTemplate, "{$form}", form) s := strings.ReplaceAll(searchTemplate, "{$form}", form)
return h.ComponentFilterFnHook(widgets.SearchFormArgs, str.Replace(s, args)) return h.ComponentFilterFnHook(widgets.Search, str.Replace(s, args))
} }

View File

@ -7,22 +7,30 @@ import (
"github.com/fthvgb1/wp-go/internal/theme/wp" "github.com/fthvgb1/wp-go/internal/theme/wp"
"github.com/fthvgb1/wp-go/internal/theme/wp/components/widget" "github.com/fthvgb1/wp-go/internal/theme/wp/components/widget"
"github.com/fthvgb1/wp-go/internal/wpconfig" "github.com/fthvgb1/wp-go/internal/wpconfig"
"strings"
) )
var widgets = map[string]func(*wp.Handle) string{ var widgets = map[string]func(*wp.Handle) string{
"search-2": widget.SearchForm, "search": widget.SearchForm,
"recent-posts-2": widget.RecentPosts, "recent-posts": widget.RecentPosts,
"recent-comments-2": widget.RecentComments, "recent-comments": widget.RecentComments,
"archives-2": widget.Archive, "archives": widget.Archive,
"categories-2": widget.Category, "categories": widget.Category,
"meta": widget.Meta,
} }
func WidgetArea(h *wp.Handle) { func WidgetArea(h *wp.Handle) {
v := wpconfig.GetPHPArrayVal("sidebars_widgets", []any{}, "sidebar-1") v := wpconfig.GetPHPArrayVal("sidebars_widgets", []any{}, "sidebar-1")
sidebar := slice.FilterAndMap(v, func(t any) (func(*wp.Handle) string, bool) { sidebar := slice.FilterAndMap(v, func(t any) (func(*wp.Handle) string, bool) {
vv := t.(string) vv := t.(string)
fn, ok := widgets[vv] ss := strings.Split(vv, "-")
id := ss[len(ss)-1]
name := strings.Join(ss[0:len(ss)-1], "-")
fn, ok := widgets[name]
if ok { if ok {
if id != "2" {
wp.SetComponentsArgsForMap(h, name, "{$id}", id)
}
return fn, true return fn, true
} }
return nil, false return nil, false