Compare commits
2 Commits
decea28316
...
ca94295eb7
Author | SHA1 | Date | |
---|---|---|---|
ca94295eb7 | |||
aaa1f3c937 |
14
README.md
14
README.md
|
@ -23,10 +23,20 @@
|
|||
|-----|--------------------------------------------|
|
||||
| 列表页 | 首页/搜索/归档/分类/标签/作者 分页列表 |
|
||||
| 详情页 | 显示内容、评论并可以添加评论(转发的php处理,需要配置php版的添加评论的url) |
|
||||
| 侧边栏 | 目前固定 近期文章、近期评论、规档、分类、条目/评论feed |
|
||||
| 侧边栏 | 目前支持旧版小工具的 近期文章、近期评论、规档、分类、其它操作 显示及设置 |
|
||||
|
||||
#### 后台设置支持程度
|
||||
|
||||
- 仪表盘
|
||||
- 外观
|
||||
- 小工具
|
||||
- 搜索
|
||||
- 规档
|
||||
- 近期文章
|
||||
- 近期评论
|
||||
- 分类
|
||||
- 其它操作
|
||||
|
||||
- 设置-
|
||||
- 常规
|
||||
- 站点标题
|
||||
|
@ -55,7 +65,7 @@
|
|||
| 列表页文章数据插件 | 整个程序表现的插件 |
|
||||
|----------------------|--------------------------------------|
|
||||
| passwordProject 密码保护 | enlighter 代码高亮(需要在后台安装enlighterjs插件) |
|
||||
| digest 自动生成指定长度的摘要 | |
|
||||
| digest 自动生成指定长度的摘要 | hiddenLogin 隐藏登录入口 |
|
||||
|
||||
#### 其它
|
||||
|
||||
|
|
|
@ -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 {
|
||||
a := slice.Map(*n.Children, func(t Node[T, K]) T {
|
||||
return t.Data
|
||||
|
|
398
helper/tree/tree_test.go
Normal file
398
helper/tree/tree_test.go
Normal 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)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
|
@ -1,9 +1,10 @@
|
|||
package widgets
|
||||
|
||||
const (
|
||||
SearchFormArgs = "SearchFormArgs"
|
||||
RecentPostsArgs = "RecentPostsArgs"
|
||||
RecentCommentsArgs = "RecentCommentsArgs"
|
||||
ArchiveArgs = "ArchiveArgs"
|
||||
Categories = "Categories"
|
||||
Search = "search"
|
||||
RecentPosts = "recent-posts"
|
||||
RecentComments = "recent-comments"
|
||||
Archive = "archives"
|
||||
Categories = "categories"
|
||||
Meta = "meta"
|
||||
)
|
||||
|
|
|
@ -3,11 +3,13 @@ package wphandle
|
|||
import (
|
||||
"github.com/fthvgb1/wp-go/helper/maps"
|
||||
"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"
|
||||
)
|
||||
|
||||
var plugins = wp.HandlePlugins{
|
||||
"enlightjs": enlightjs.EnlighterJS,
|
||||
"enlightjs": enlightjs.EnlighterJS,
|
||||
"hiddenLogin": hiddenlogin.HiddenLogin,
|
||||
}
|
||||
|
||||
func Plugins() wp.HandlePlugins {
|
||||
|
|
17
internal/plugins/wphandle/hiddenlogin/hiddenlogin.go
Normal file
17
internal/plugins/wphandle/hiddenlogin/hiddenlogin.go
Normal 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>`: "",
|
||||
})
|
||||
})
|
||||
}
|
|
@ -1,14 +1,5 @@
|
|||
{{define "layout/sidebar" }}
|
||||
<div id="widget-area" class="widget-area" role="complementary">
|
||||
{{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>
|
||||
{{end}}
|
|
@ -43,7 +43,7 @@ func Hook(h *wp.Handle) {
|
|||
func dispatch(next wp.HandleFn[*wp.Handle], h *wp.Handle) {
|
||||
components.WidgetArea(h)
|
||||
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"`)
|
||||
})
|
||||
wphandle.RegisterPlugins(h, config.GetConfig().Plugins...)
|
||||
|
|
|
@ -1,25 +1,3 @@
|
|||
{{define "layout/sidebar" }}
|
||||
{{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}}
|
|
@ -10,6 +10,7 @@ import (
|
|||
"github.com/fthvgb1/wp-go/internal/cmd/reload"
|
||||
"github.com/fthvgb1/wp-go/internal/pkg/config"
|
||||
"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/models"
|
||||
"github.com/fthvgb1/wp-go/internal/plugins"
|
||||
|
@ -61,9 +62,29 @@ func ready(next wp.HandleFn[*wp.Handle], h *wp.Handle) {
|
|||
pushScripts(h)
|
||||
h.SetData("HeaderImage", getHeaderImage(h))
|
||||
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)
|
||||
}
|
||||
|
||||
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) {
|
||||
switch h.Scene() {
|
||||
case constraints.Detail:
|
||||
|
|
|
@ -36,6 +36,9 @@ func (h *Handle) BodyClass(class ...string) string {
|
|||
case constraints.Category, constraints.Tag:
|
||||
class = append(class, "archive", "category")
|
||||
cat := h.Index.Param.Category
|
||||
if cat == "" {
|
||||
break
|
||||
}
|
||||
_, cate := slice.SearchFirst(cache.CategoriesTags(h.C, h.scene), func(my models.TermsMy) bool {
|
||||
return my.Name == cat
|
||||
})
|
||||
|
|
|
@ -49,17 +49,20 @@ var archiveTemplate = `{$before_widget}
|
|||
`
|
||||
|
||||
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)
|
||||
conf := wpconfig.GetPHPArrayVal("widget_archives", archivesConfig.Load(), int64(2))
|
||||
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
|
||||
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(widgets.ArchiveArgs, str.Replace(s, args))
|
||||
return h.ComponentFilterFnHook(widgets.Archive, str.Replace(s, args))
|
||||
}
|
||||
|
||||
var dropdownScript = `
|
||||
|
|
|
@ -36,7 +36,7 @@ var categoryConfig = func() safety.Var[map[any]any] {
|
|||
"{$class}": "postform",
|
||||
"{$show_option_none}": "选择分类",
|
||||
"{$name}": "cat",
|
||||
"{$id}": "cat",
|
||||
"{$selectId}": "cat",
|
||||
"{$required}": "",
|
||||
"{$nav}": "",
|
||||
"{$navCloser}": "",
|
||||
|
@ -64,6 +64,9 @@ func Category(h *wp.Handle) string {
|
|||
args["{$title}"] = str.Join(args["{$before_title}"], conf["title"].(string), args["{$after_title}"])
|
||||
t := categoryTemplate
|
||||
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)
|
||||
if dropdown == 1 {
|
||||
t = strings.ReplaceAll(t, "{$html}", categoryDropdown(h, args, conf, categories))
|
||||
|
@ -71,7 +74,7 @@ func Category(h *wp.Handle) string {
|
|||
} else {
|
||||
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 {
|
||||
|
@ -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.Sprintf(` <label class="screen-reader-text" for="%s">%s</label>
|
||||
`, args["{$id}"], args["{$title}"])
|
||||
`, args["{$selectId}"], args["{$title}"])
|
||||
if len(categories) > 0 {
|
||||
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>
|
||||
`, args["{$show_option_none}"])
|
||||
currentCategory := ""
|
||||
|
@ -218,7 +221,7 @@ func categoryDropdown(h *wp.Handle, args map[string]string, conf map[any]any, ca
|
|||
}
|
||||
s.Sprintf(`<script%s>
|
||||
`, attr)
|
||||
s.Sprintf(categoryDropdownJs, args["{$id}"])
|
||||
s.Sprintf(categoryDropdownJs, args["{$selectId}"])
|
||||
s.WriteString("</script>\n")
|
||||
return s.String()
|
||||
}
|
||||
|
|
64
internal/theme/wp/components/widget/meta.go
Normal file
64
internal/theme/wp/components/widget/meta.go
Normal 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))
|
||||
}
|
|
@ -48,11 +48,14 @@ var recentCommentsTemplate = `{$before_widget}
|
|||
`
|
||||
|
||||
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)
|
||||
conf := wpconfig.GetPHPArrayVal("widget_recent-comments", recentCommentConf.Load(), int64(2))
|
||||
conf = maps.FilterZeroMerge(recentCommentConf.Load(), conf)
|
||||
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") {
|
||||
args["{$nav}"] = fmt.Sprintf(`<nav aria-label="%s">`, conf["title"])
|
||||
args["{$navCloser}"] = "</nav>"
|
||||
|
@ -65,5 +68,5 @@ func RecentComments(h *wp.Handle) string {
|
|||
</li>`, t.CommentAuthor, t.CommentId, t.CommentPostId, t.PostTitle)
|
||||
})
|
||||
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))
|
||||
}
|
||||
|
|
|
@ -50,10 +50,13 @@ var recentConf = func() safety.Var[map[any]any] {
|
|||
}()
|
||||
|
||||
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)
|
||||
conf := wpconfig.GetPHPArrayVal[map[any]any]("widget_recent-posts", recentConf.Load(), int64(2))
|
||||
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}"])
|
||||
if slice.IsContained(h.CommonThemeMods().ThemeSupport.HTML5, "navigation-widgets") {
|
||||
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)
|
||||
})
|
||||
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))
|
||||
}
|
||||
|
|
|
@ -21,12 +21,14 @@ var searchTemplate = `{$before_widget}
|
|||
var searchArgs = func() safety.Var[map[string]string] {
|
||||
v := safety.Var[map[string]string]{}
|
||||
v.Store(map[string]string{
|
||||
"{$id}": "2",
|
||||
"{$before_widget}": `<aside id="search-2" class="widget widget_search">`,
|
||||
"{$after_widget}": `</aside>`,
|
||||
"{$aria_label}": "",
|
||||
"{$title}": "",
|
||||
"{$before_title}": `<h2 class="widget-title">`,
|
||||
"{$after_title}": `</h2>`,
|
||||
"{$form}": "",
|
||||
"{$button}": "搜索",
|
||||
"{$placeholder}": "搜索…",
|
||||
"{$label}": "搜索:",
|
||||
|
@ -50,11 +52,14 @@ var xmlSearchForm = `<form role="search" {$aria_label} method="get" id="searchfo
|
|||
</form>`
|
||||
|
||||
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)
|
||||
if args["{$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}"] != "" {
|
||||
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)
|
||||
}
|
||||
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
|
||||
}
|
||||
s := strings.ReplaceAll(searchTemplate, "{$form}", form)
|
||||
return h.ComponentFilterFnHook(widgets.SearchFormArgs, str.Replace(s, args))
|
||||
return h.ComponentFilterFnHook(widgets.Search, str.Replace(s, args))
|
||||
}
|
||||
|
|
|
@ -7,22 +7,30 @@ import (
|
|||
"github.com/fthvgb1/wp-go/internal/theme/wp"
|
||||
"github.com/fthvgb1/wp-go/internal/theme/wp/components/widget"
|
||||
"github.com/fthvgb1/wp-go/internal/wpconfig"
|
||||
"strings"
|
||||
)
|
||||
|
||||
var widgets = map[string]func(*wp.Handle) string{
|
||||
"search-2": widget.SearchForm,
|
||||
"recent-posts-2": widget.RecentPosts,
|
||||
"recent-comments-2": widget.RecentComments,
|
||||
"archives-2": widget.Archive,
|
||||
"categories-2": widget.Category,
|
||||
"search": widget.SearchForm,
|
||||
"recent-posts": widget.RecentPosts,
|
||||
"recent-comments": widget.RecentComments,
|
||||
"archives": widget.Archive,
|
||||
"categories": widget.Category,
|
||||
"meta": widget.Meta,
|
||||
}
|
||||
|
||||
func WidgetArea(h *wp.Handle) {
|
||||
v := wpconfig.GetPHPArrayVal("sidebars_widgets", []any{}, "sidebar-1")
|
||||
sidebar := slice.FilterAndMap(v, func(t any) (func(*wp.Handle) string, bool) {
|
||||
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 id != "2" {
|
||||
wp.SetComponentsArgsForMap(h, name, "{$id}", id)
|
||||
}
|
||||
return fn, true
|
||||
}
|
||||
return nil, false
|
||||
|
|
Loading…
Reference in New Issue
Block a user