commit
f470a0c31f
@ -71,3 +71,7 @@ trustIps: []
|
|||||||
trustServerNames: ["xy.test","blog.xy.test"]
|
trustServerNames: ["xy.test","blog.xy.test"]
|
||||||
# port
|
# port
|
||||||
port: 8082
|
port: 8082
|
||||||
|
# 主题 为空值为option template,没有就默认为twentyfifteen
|
||||||
|
theme: "twentyfifteen"
|
||||||
|
# 文档排序默认升序还是降序
|
||||||
|
postOrder: "desc"
|
1
helper/html/a.gohtml
Normal file
1
helper/html/a.gohtml
Normal file
@ -0,0 +1 @@
|
|||||||
|
{{.xx}}
|
@ -1,9 +1,11 @@
|
|||||||
package html
|
package html
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"bytes"
|
||||||
"fmt"
|
"fmt"
|
||||||
"github.com/dlclark/regexp2"
|
"github.com/dlclark/regexp2"
|
||||||
"github.com/fthvgb1/wp-go/helper/slice"
|
"github.com/fthvgb1/wp-go/helper/slice"
|
||||||
|
"html/template"
|
||||||
"regexp"
|
"regexp"
|
||||||
"strings"
|
"strings"
|
||||||
)
|
)
|
||||||
@ -164,3 +166,13 @@ func UnClosedTag(s []string) []string {
|
|||||||
i++
|
i++
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func RenderedHtml(t *template.Template, data map[string]any) (r string, err error) {
|
||||||
|
var buf bytes.Buffer
|
||||||
|
err = t.Execute(&buf, data)
|
||||||
|
if err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
r = buf.String()
|
||||||
|
return
|
||||||
|
}
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
package html
|
package html
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"html/template"
|
||||||
"reflect"
|
"reflect"
|
||||||
"testing"
|
"testing"
|
||||||
)
|
)
|
||||||
@ -228,3 +229,46 @@ func Test_clearTag(t *testing.T) {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestRenderedHtml(t *testing.T) {
|
||||||
|
type args struct {
|
||||||
|
t *template.Template
|
||||||
|
data map[string]any
|
||||||
|
}
|
||||||
|
tests := []struct {
|
||||||
|
name string
|
||||||
|
args args
|
||||||
|
wantR string
|
||||||
|
wantErr bool
|
||||||
|
}{
|
||||||
|
{
|
||||||
|
name: "t1",
|
||||||
|
args: args{
|
||||||
|
t: func() *template.Template {
|
||||||
|
tt, err := template.ParseFiles("./a.gohtml")
|
||||||
|
if err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
return tt
|
||||||
|
}(),
|
||||||
|
data: map[string]any{
|
||||||
|
"xx": "oo",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
wantR: "oo",
|
||||||
|
wantErr: false,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
for _, tt := range tests {
|
||||||
|
t.Run(tt.name, func(t *testing.T) {
|
||||||
|
gotR, err := RenderedHtml(tt.args.t, tt.args.data)
|
||||||
|
if (err != nil) != tt.wantErr {
|
||||||
|
t.Errorf("RenderedHtml() error = %v, wantErr %v", err, tt.wantErr)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if gotR != tt.wantR {
|
||||||
|
t.Errorf("RenderedHtml() gotR = %v, want %v", gotR, tt.wantR)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
114
helper/slice/set.go
Normal file
114
helper/slice/set.go
Normal file
@ -0,0 +1,114 @@
|
|||||||
|
package slice
|
||||||
|
|
||||||
|
func IsContained[T comparable](a T, arr []T) bool {
|
||||||
|
for _, v := range arr {
|
||||||
|
if a == v {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
func IsContainedByFn[T any](a []T, e T, fn func(i, j T) bool) bool {
|
||||||
|
for _, t := range a {
|
||||||
|
if fn(e, t) {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
// Diff return elements which in a and not in b,...
|
||||||
|
func Diff[T comparable](a []T, b ...[]T) (r []T) {
|
||||||
|
for _, t := range a {
|
||||||
|
f := false
|
||||||
|
for _, ts := range b {
|
||||||
|
if IsContained(t, ts) {
|
||||||
|
f = true
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if f {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
r = append(r, t)
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
func DiffByFn[T any](a []T, fn func(i, j T) bool, b ...[]T) (r []T) {
|
||||||
|
for _, t := range a {
|
||||||
|
f := false
|
||||||
|
for _, ts := range b {
|
||||||
|
if IsContainedByFn(ts, t, fn) {
|
||||||
|
f = true
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if f {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
r = append(r, t)
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
func Intersect[T comparable](a []T, b ...[]T) (r []T) {
|
||||||
|
for _, t := range a {
|
||||||
|
f := false
|
||||||
|
for _, ts := range b {
|
||||||
|
if !IsContained(t, ts) {
|
||||||
|
f = true
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if f {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
r = append(r, t)
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
func IntersectByFn[T any](a []T, fn func(i, j T) bool, b ...[]T) (r []T) {
|
||||||
|
for _, t := range a {
|
||||||
|
f := false
|
||||||
|
for _, ts := range b {
|
||||||
|
if !IsContainedByFn(ts, t, fn) {
|
||||||
|
f = true
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if f {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
r = append(r, t)
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
func Unique[T comparable](a ...[]T) (r []T) {
|
||||||
|
m := map[T]struct{}{}
|
||||||
|
for _, ts := range a {
|
||||||
|
for _, t := range ts {
|
||||||
|
if _, ok := m[t]; !ok {
|
||||||
|
m[t] = struct{}{}
|
||||||
|
r = append(r, t)
|
||||||
|
} else {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
func UniqueByFn[T any](fn func(T, T) bool, a ...[]T) (r []T) {
|
||||||
|
for _, ts := range a {
|
||||||
|
for _, t := range ts {
|
||||||
|
if !IsContainedByFn(r, t, fn) {
|
||||||
|
r = append(r, t)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return r
|
||||||
|
}
|
211
helper/slice/set_test.go
Normal file
211
helper/slice/set_test.go
Normal file
@ -0,0 +1,211 @@
|
|||||||
|
package slice
|
||||||
|
|
||||||
|
import (
|
||||||
|
"github.com/fthvgb1/wp-go/helper/number"
|
||||||
|
"reflect"
|
||||||
|
"testing"
|
||||||
|
)
|
||||||
|
|
||||||
|
type x struct {
|
||||||
|
int
|
||||||
|
y string
|
||||||
|
}
|
||||||
|
|
||||||
|
func y(i []int) []x {
|
||||||
|
return Map(i, func(t int) x {
|
||||||
|
return x{t, ""}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestDiff(t *testing.T) {
|
||||||
|
type args[T int] struct {
|
||||||
|
a []T
|
||||||
|
b [][]T
|
||||||
|
}
|
||||||
|
type testCase[T int] struct {
|
||||||
|
name string
|
||||||
|
args args[T]
|
||||||
|
wantR []T
|
||||||
|
}
|
||||||
|
tests := []testCase[int]{
|
||||||
|
{
|
||||||
|
name: "t1",
|
||||||
|
args: args[int]{
|
||||||
|
a: number.Range(1, 10, 1),
|
||||||
|
b: [][]int{number.Range(3, 7, 1), number.Range(6, 9, 1)},
|
||||||
|
},
|
||||||
|
wantR: []int{1, 2, 10},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
for _, tt := range tests {
|
||||||
|
t.Run(tt.name, func(t *testing.T) {
|
||||||
|
if gotR := Diff(tt.args.a, tt.args.b...); !reflect.DeepEqual(gotR, tt.wantR) {
|
||||||
|
t.Errorf("Diff() = %v, want %v", gotR, tt.wantR)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestDiffByFn(t *testing.T) {
|
||||||
|
|
||||||
|
type args[T x] struct {
|
||||||
|
a []T
|
||||||
|
fn func(i, j T) bool
|
||||||
|
b [][]T
|
||||||
|
}
|
||||||
|
type testCase[T x] struct {
|
||||||
|
name string
|
||||||
|
args args[T]
|
||||||
|
wantR []T
|
||||||
|
}
|
||||||
|
tests := []testCase[x]{
|
||||||
|
{
|
||||||
|
name: "t1",
|
||||||
|
args: args[x]{
|
||||||
|
a: y(number.Range(1, 10, 1)),
|
||||||
|
fn: func(i, j x) bool {
|
||||||
|
return i.int == j.int
|
||||||
|
},
|
||||||
|
b: [][]x{
|
||||||
|
y(number.Range(3, 7, 1)),
|
||||||
|
y(number.Range(6, 9, 1)),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
wantR: []x{{1, ""}, {2, ""}, {10, ""}},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
for _, tt := range tests {
|
||||||
|
t.Run(tt.name, func(t *testing.T) {
|
||||||
|
if gotR := DiffByFn(tt.args.a, tt.args.fn, tt.args.b...); !reflect.DeepEqual(gotR, tt.wantR) {
|
||||||
|
t.Errorf("DiffByFn() = %v, want %v", gotR, tt.wantR)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestIntersect(t *testing.T) {
|
||||||
|
type args[T int] struct {
|
||||||
|
a []T
|
||||||
|
b [][]T
|
||||||
|
}
|
||||||
|
type testCase[T int] struct {
|
||||||
|
name string
|
||||||
|
args args[T]
|
||||||
|
wantR []T
|
||||||
|
}
|
||||||
|
tests := []testCase[int]{
|
||||||
|
{
|
||||||
|
name: "t1",
|
||||||
|
args: args[int]{
|
||||||
|
a: number.Range(1, 10, 1),
|
||||||
|
b: [][]int{number.Range(3, 7, 1), number.Range(6, 9, 1)},
|
||||||
|
},
|
||||||
|
wantR: []int{6, 7},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
for _, tt := range tests {
|
||||||
|
t.Run(tt.name, func(t *testing.T) {
|
||||||
|
if gotR := Intersect(tt.args.a, tt.args.b...); !reflect.DeepEqual(gotR, tt.wantR) {
|
||||||
|
t.Errorf("Intersect() = %v, want %v", gotR, tt.wantR)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestIntersectByFn(t *testing.T) {
|
||||||
|
type args[T x] struct {
|
||||||
|
a []T
|
||||||
|
fn func(i, j T) bool
|
||||||
|
b [][]T
|
||||||
|
}
|
||||||
|
type testCase[T x] struct {
|
||||||
|
name string
|
||||||
|
args args[T]
|
||||||
|
wantR []T
|
||||||
|
}
|
||||||
|
tests := []testCase[x]{
|
||||||
|
{
|
||||||
|
name: "t1",
|
||||||
|
args: args[x]{
|
||||||
|
a: y(number.Range(1, 10, 1)),
|
||||||
|
fn: func(i, j x) bool {
|
||||||
|
return i.int == j.int
|
||||||
|
},
|
||||||
|
b: [][]x{
|
||||||
|
y(number.Range(3, 7, 1)),
|
||||||
|
y(number.Range(6, 9, 1)),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
wantR: []x{{6, ""}, {7, ""}},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
for _, tt := range tests {
|
||||||
|
t.Run(tt.name, func(t *testing.T) {
|
||||||
|
if gotR := IntersectByFn(tt.args.a, tt.args.fn, tt.args.b...); !reflect.DeepEqual(gotR, tt.wantR) {
|
||||||
|
t.Errorf("IntersectByFn() = %v, want %v", gotR, tt.wantR)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestUnique(t *testing.T) {
|
||||||
|
type args[T int] struct {
|
||||||
|
a [][]T
|
||||||
|
}
|
||||||
|
type testCase[T int] struct {
|
||||||
|
name string
|
||||||
|
args args[T]
|
||||||
|
wantR []T
|
||||||
|
}
|
||||||
|
tests := []testCase[int]{
|
||||||
|
{
|
||||||
|
name: "t1",
|
||||||
|
args: args[int]{
|
||||||
|
a: [][]int{
|
||||||
|
number.Range(1, 5, 1),
|
||||||
|
number.Range(3, 6, 1),
|
||||||
|
number.Range(6, 15, 1),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
wantR: number.Range(1, 15, 1),
|
||||||
|
},
|
||||||
|
}
|
||||||
|
for _, tt := range tests {
|
||||||
|
t.Run(tt.name, func(t *testing.T) {
|
||||||
|
if gotR := Unique(tt.args.a...); !reflect.DeepEqual(gotR, tt.wantR) {
|
||||||
|
t.Errorf("Unique() = %v, want %v", gotR, tt.wantR)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestUniqueByFn(t *testing.T) {
|
||||||
|
type args[T x] struct {
|
||||||
|
fn func(T, T) bool
|
||||||
|
a [][]T
|
||||||
|
}
|
||||||
|
type testCase[T x] struct {
|
||||||
|
name string
|
||||||
|
args args[T]
|
||||||
|
wantR []T
|
||||||
|
}
|
||||||
|
tests := []testCase[x]{
|
||||||
|
{
|
||||||
|
name: "t1",
|
||||||
|
args: args[x]{
|
||||||
|
fn: func(i, j x) bool {
|
||||||
|
return i.int == j.int
|
||||||
|
},
|
||||||
|
a: [][]x{y([]int{1, 1, 2, 2, 3, 3}), y([]int{2, 2, 4, 4})},
|
||||||
|
},
|
||||||
|
wantR: y([]int{1, 2, 3, 4}),
|
||||||
|
},
|
||||||
|
}
|
||||||
|
for _, tt := range tests {
|
||||||
|
t.Run(tt.name, func(t *testing.T) {
|
||||||
|
if gotR := UniqueByFn(tt.args.fn, tt.args.a...); !reflect.DeepEqual(gotR, tt.wantR) {
|
||||||
|
t.Errorf("UniqueByFn() = %v, want %v", gotR, tt.wantR)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
@ -1,5 +1,7 @@
|
|||||||
package slice
|
package slice
|
||||||
|
|
||||||
|
import "github.com/fthvgb1/wp-go/helper"
|
||||||
|
|
||||||
func Map[T, R any](arr []T, fn func(T) R) []R {
|
func Map[T, R any](arr []T, fn func(T) R) []R {
|
||||||
r := make([]R, 0, len(arr))
|
r := make([]R, 0, len(arr))
|
||||||
for _, t := range arr {
|
for _, t := range arr {
|
||||||
@ -146,11 +148,19 @@ func Comb[T any](arr []T, m int) (r [][]T) {
|
|||||||
return r
|
return r
|
||||||
}
|
}
|
||||||
|
|
||||||
func IsContained[T comparable](a T, arr []T) bool {
|
func GroupBy[K comparable, T, V any](a []T, fn func(T) (K, V)) map[K][]V {
|
||||||
for _, v := range arr {
|
r := make(map[K][]V)
|
||||||
if a == v {
|
for _, t := range a {
|
||||||
return true
|
k, v := fn(t)
|
||||||
|
if _, ok := r[k]; !ok {
|
||||||
|
r[k] = []V{v}
|
||||||
|
} else {
|
||||||
|
r[k] = append(r[k], v)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return false
|
return r
|
||||||
|
}
|
||||||
|
|
||||||
|
func ToAnySlice[T any](a []T) []any {
|
||||||
|
return Map(a, helper.ToAny[T])
|
||||||
}
|
}
|
||||||
|
@ -463,3 +463,67 @@ func TestFilterAndMap(t *testing.T) {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestGroupBy(t *testing.T) {
|
||||||
|
type args[T x, K int, V string] struct {
|
||||||
|
a []T
|
||||||
|
fn func(T) (K, V)
|
||||||
|
}
|
||||||
|
type testCase[T x, K int, V string] struct {
|
||||||
|
name string
|
||||||
|
args args[T, K, V]
|
||||||
|
want map[K][]V
|
||||||
|
}
|
||||||
|
tests := []testCase[x, int, string]{
|
||||||
|
{
|
||||||
|
name: "t1",
|
||||||
|
args: args[x, int, string]{
|
||||||
|
a: Map([]int{1, 1, 2, 2, 3, 3, 4, 4, 5, 5}, func(t int) x {
|
||||||
|
return x{t, number.ToString(t)}
|
||||||
|
}),
|
||||||
|
fn: func(v x) (int, string) {
|
||||||
|
return v.int, v.y
|
||||||
|
},
|
||||||
|
},
|
||||||
|
want: map[int][]string{
|
||||||
|
1: {"1", "1"},
|
||||||
|
2: {"2", "2"},
|
||||||
|
3: {"3", "3"},
|
||||||
|
4: {"4", "4"},
|
||||||
|
5: {"5", "5"},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
for _, tt := range tests {
|
||||||
|
t.Run(tt.name, func(t *testing.T) {
|
||||||
|
if got := GroupBy(tt.args.a, tt.args.fn); !reflect.DeepEqual(got, tt.want) {
|
||||||
|
t.Errorf("GroupBy() = %v, want %v", got, tt.want)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestToAnySlice(t *testing.T) {
|
||||||
|
type args[T int] struct {
|
||||||
|
a []T
|
||||||
|
}
|
||||||
|
type testCase[T int] struct {
|
||||||
|
name string
|
||||||
|
args args[T]
|
||||||
|
want []any
|
||||||
|
}
|
||||||
|
tests := []testCase[int]{
|
||||||
|
{
|
||||||
|
name: "t1",
|
||||||
|
args: args[int]{number.Range(1, 5, 1)},
|
||||||
|
want: []any{1, 2, 3, 4, 5},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
for _, tt := range tests {
|
||||||
|
t.Run(tt.name, func(t *testing.T) {
|
||||||
|
if got := ToAnySlice(tt.args.a); !reflect.DeepEqual(got, tt.want) {
|
||||||
|
t.Errorf("ToAnySlice() = %v, want %v", got, tt.want)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@ -2,7 +2,6 @@ package actions
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
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/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"
|
||||||
@ -30,7 +29,7 @@ func Detail(c *gin.Context) {
|
|||||||
archive := cache.Archives(c)
|
archive := cache.Archives(c)
|
||||||
categoryItems := cache.Categories(c)
|
categoryItems := cache.Categories(c)
|
||||||
recentComments := cache.RecentComments(c, 5)
|
recentComments := cache.RecentComments(c, 5)
|
||||||
var h = gin.H{
|
var ginH = gin.H{
|
||||||
"title": wpconfig.Options.Value("blogname"),
|
"title": wpconfig.Options.Value("blogname"),
|
||||||
"options": wpconfig.Options,
|
"options": wpconfig.Options,
|
||||||
"recentPosts": recent,
|
"recentPosts": recent,
|
||||||
@ -39,17 +38,21 @@ func Detail(c *gin.Context) {
|
|||||||
"recentComments": recentComments,
|
"recentComments": recentComments,
|
||||||
}
|
}
|
||||||
isApproveComment := false
|
isApproveComment := false
|
||||||
|
status := plugins.Ok
|
||||||
defer func() {
|
defer func() {
|
||||||
status := http.StatusOK
|
code := http.StatusOK
|
||||||
if err != nil {
|
if err != nil {
|
||||||
status = http.StatusInternalServerError
|
code = http.StatusNotFound
|
||||||
c.Error(err)
|
c.Error(err)
|
||||||
|
status = plugins.Error
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
if isApproveComment == true {
|
if isApproveComment == true {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
c.HTML(status, str.Join(theme.GetTemplateName(), "/posts/detail.gohtml"), h)
|
|
||||||
|
t := theme.GetTemplateName()
|
||||||
|
theme.Hook(t, code, c, ginH, plugins.Detail, status)
|
||||||
}()
|
}()
|
||||||
id := c.Param("id")
|
id := c.Param("id")
|
||||||
Id := 0
|
Id := 0
|
||||||
@ -92,19 +95,19 @@ func Detail(c *gin.Context) {
|
|||||||
commentss := treeComments(comments)
|
commentss := treeComments(comments)
|
||||||
prev, next, err := cache.GetContextPost(c, post.Id, post.PostDate)
|
prev, next, err := cache.GetContextPost(c, post.Id, post.PostDate)
|
||||||
logs.ErrPrintln(err, "get pre and next post", post.Id, post.PostDate)
|
logs.ErrPrintln(err, "get pre and next post", post.Id, post.PostDate)
|
||||||
h["title"] = fmt.Sprintf("%s-%s", post.PostTitle, wpconfig.Options.Value("blogname"))
|
ginH["title"] = fmt.Sprintf("%s-%s", post.PostTitle, wpconfig.Options.Value("blogname"))
|
||||||
h["post"] = post
|
ginH["post"] = post
|
||||||
h["showComment"] = showComment
|
ginH["showComment"] = showComment
|
||||||
h["prev"] = prev
|
ginH["prev"] = prev
|
||||||
depth := wpconfig.Options.Value("thread_comments_depth")
|
depth := wpconfig.Options.Value("thread_comments_depth")
|
||||||
d, err := strconv.Atoi(depth)
|
d, err := strconv.Atoi(depth)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
logs.ErrPrintln(err, "get comment depth")
|
logs.ErrPrintln(err, "get comment depth ", depth)
|
||||||
d = 5
|
d = 5
|
||||||
}
|
}
|
||||||
h["comments"] = hh.formatComment(commentss, 1, d)
|
ginH["comments"] = hh.formatComment(commentss, 1, d)
|
||||||
h["next"] = next
|
ginH["next"] = next
|
||||||
h["user"] = user
|
ginH["user"] = user
|
||||||
}
|
}
|
||||||
|
|
||||||
type Comment struct {
|
type Comment struct {
|
||||||
|
@ -7,6 +7,7 @@ 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/config"
|
||||||
"github.com/fthvgb1/wp-go/internal/pkg/dao"
|
"github.com/fthvgb1/wp-go/internal/pkg/dao"
|
||||||
"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"
|
||||||
@ -92,10 +93,17 @@ func (h *indexHandle) getSearchKey() string {
|
|||||||
return fmt.Sprintf("action:%s|%s|%s|%s|%s|%s|%d|%d", h.author, h.search, h.orderBy, h.order, h.category, h.categoryType, h.page, h.pageSize)
|
return fmt.Sprintf("action:%s|%s|%s|%s|%s|%s|%d|%d", h.author, h.search, h.orderBy, h.order, h.category, h.categoryType, h.page, h.pageSize)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var orders = []string{"asc", "desc"}
|
||||||
|
|
||||||
func (h *indexHandle) parseParams() (err error) {
|
func (h *indexHandle) parseParams() (err error) {
|
||||||
h.order = h.c.Query("order")
|
h.order = h.c.Query("order")
|
||||||
if !slice.IsContained(h.order, []string{"asc", "desc"}) {
|
|
||||||
|
if !slice.IsContained(h.order, orders) {
|
||||||
|
order := config.Conf.Load().PostOrder
|
||||||
h.order = "asc"
|
h.order = "asc"
|
||||||
|
if order != "" && slice.IsContained(order, orders) {
|
||||||
|
h.order = order
|
||||||
|
}
|
||||||
}
|
}
|
||||||
year := h.c.Param("year")
|
year := h.c.Param("year")
|
||||||
if year != "" {
|
if year != "" {
|
||||||
|
@ -21,6 +21,7 @@ func RecoverAndSendMail(w io.Writer) func(ctx *gin.Context) {
|
|||||||
return gin.CustomRecoveryWithWriter(w, func(ctx *gin.Context, err any) {
|
return gin.CustomRecoveryWithWriter(w, func(ctx *gin.Context, err any) {
|
||||||
c := ctx.Copy()
|
c := ctx.Copy()
|
||||||
stack := stack(4)
|
stack := stack(4)
|
||||||
|
if gin.Mode() == gin.ReleaseMode {
|
||||||
go func() {
|
go func() {
|
||||||
httpRequest, _ := httputil.DumpRequest(c.Request, true)
|
httpRequest, _ := httputil.DumpRequest(c.Request, true)
|
||||||
headers := strings.Split(string(httpRequest), "\r\n")
|
headers := strings.Split(string(httpRequest), "\r\n")
|
||||||
@ -49,6 +50,8 @@ func RecoverAndSendMail(w io.Writer) func(ctx *gin.Context) {
|
|||||||
logs.ErrPrintln(er, "recover send mail fail", fmt.Sprintf("%v", err))
|
logs.ErrPrintln(er, "recover send mail fail", fmt.Sprintf("%v", err))
|
||||||
}
|
}
|
||||||
}()
|
}()
|
||||||
|
}
|
||||||
|
|
||||||
ctx.AbortWithStatus(http.StatusInternalServerError)
|
ctx.AbortWithStatus(http.StatusInternalServerError)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
@ -38,6 +38,7 @@ type Config struct {
|
|||||||
TrustIps []string `yaml:"trustIps"`
|
TrustIps []string `yaml:"trustIps"`
|
||||||
TrustServerNames []string `yaml:"trustServerNames"`
|
TrustServerNames []string `yaml:"trustServerNames"`
|
||||||
Theme string `yaml:"theme"`
|
Theme string `yaml:"theme"`
|
||||||
|
PostOrder string `yaml:"postOrder"`
|
||||||
}
|
}
|
||||||
|
|
||||||
type Mail struct {
|
type Mail struct {
|
||||||
|
@ -2,7 +2,6 @@ package dao
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
"github.com/fthvgb1/wp-go/helper"
|
|
||||||
"github.com/fthvgb1/wp-go/helper/slice"
|
"github.com/fthvgb1/wp-go/helper/slice"
|
||||||
"github.com/fthvgb1/wp-go/internal/pkg/models"
|
"github.com/fthvgb1/wp-go/internal/pkg/models"
|
||||||
"github.com/fthvgb1/wp-go/model"
|
"github.com/fthvgb1/wp-go/model"
|
||||||
@ -48,7 +47,7 @@ func GetCommentByIds(args ...any) (map[uint64]models.Comments, error) {
|
|||||||
m := make(map[uint64]models.Comments)
|
m := make(map[uint64]models.Comments)
|
||||||
r, err := model.SimpleFind[models.Comments](ctx, model.SqlBuilder{
|
r, err := model.SimpleFind[models.Comments](ctx, model.SqlBuilder{
|
||||||
{"comment_ID", "in", ""}, {"comment_approved", "1"},
|
{"comment_ID", "in", ""}, {"comment_approved", "1"},
|
||||||
}, "*", slice.Map(ids, helper.ToAny[uint64]))
|
}, "*", slice.ToAnySlice(ids))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return m, err
|
return m, err
|
||||||
}
|
}
|
||||||
|
@ -3,7 +3,6 @@ package dao
|
|||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
"fmt"
|
"fmt"
|
||||||
"github.com/fthvgb1/wp-go/helper"
|
|
||||||
"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"
|
||||||
"github.com/fthvgb1/wp-go/internal/pkg/logs"
|
"github.com/fthvgb1/wp-go/internal/pkg/logs"
|
||||||
@ -19,7 +18,7 @@ func GetPostMetaByPostIds(args ...any) (r map[uint64]map[string]any, err error)
|
|||||||
ids := args[1].([]uint64)
|
ids := args[1].([]uint64)
|
||||||
rr, err := model.Find[models.Postmeta](ctx, model.SqlBuilder{
|
rr, err := model.Find[models.Postmeta](ctx, model.SqlBuilder{
|
||||||
{"post_id", "in", ""},
|
{"post_id", "in", ""},
|
||||||
}, "*", "", nil, nil, nil, 0, slice.Map(ids, helper.ToAny[uint64]))
|
}, "*", "", nil, nil, nil, 0, slice.ToAnySlice(ids))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
@ -93,6 +92,7 @@ func thumbnail(metadata models.WpAttachmentMetadata, thumbType, host string) (r
|
|||||||
} else if r.Width >= 767 {
|
} else if r.Width >= 767 {
|
||||||
r.Sizes = "(max-width: 767px) 89vw, (max-width: 1000px) 54vw, (max-width: 1071px) 543px, 580px"
|
r.Sizes = "(max-width: 767px) 89vw, (max-width: 1000px) 54vw, (max-width: 1071px) 543px, 580px"
|
||||||
}
|
}
|
||||||
|
r.OriginAttachmentData = metadata
|
||||||
}
|
}
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
@ -4,7 +4,6 @@ import (
|
|||||||
"context"
|
"context"
|
||||||
"database/sql"
|
"database/sql"
|
||||||
"fmt"
|
"fmt"
|
||||||
"github.com/fthvgb1/wp-go/helper"
|
|
||||||
"github.com/fthvgb1/wp-go/helper/slice"
|
"github.com/fthvgb1/wp-go/helper/slice"
|
||||||
"github.com/fthvgb1/wp-go/internal/pkg/models"
|
"github.com/fthvgb1/wp-go/internal/pkg/models"
|
||||||
"github.com/fthvgb1/wp-go/internal/wpconfig"
|
"github.com/fthvgb1/wp-go/internal/wpconfig"
|
||||||
@ -18,7 +17,7 @@ func GetPostsByIds(ids ...any) (m map[uint64]models.Posts, err error) {
|
|||||||
ctx := ids[0].(context.Context)
|
ctx := ids[0].(context.Context)
|
||||||
m = make(map[uint64]models.Posts)
|
m = make(map[uint64]models.Posts)
|
||||||
id := ids[1].([]uint64)
|
id := ids[1].([]uint64)
|
||||||
arg := slice.Map(id, helper.ToAny[uint64])
|
arg := slice.ToAnySlice(id)
|
||||||
rawPosts, err := model.Find[models.Posts](ctx, model.SqlBuilder{{
|
rawPosts, err := model.Find[models.Posts](ctx, model.SqlBuilder{{
|
||||||
"Id", "in", "",
|
"Id", "in", "",
|
||||||
}}, "a.*,ifnull(d.name,'') category_name,ifnull(taxonomy,'') `taxonomy`", "", nil, model.SqlBuilder{{
|
}}, "a.*,ifnull(d.name,'') category_name,ifnull(taxonomy,'') `taxonomy`", "", nil, model.SqlBuilder{{
|
||||||
|
@ -38,12 +38,16 @@ type Posts struct {
|
|||||||
AttachmentMetadata WpAttachmentMetadata
|
AttachmentMetadata WpAttachmentMetadata
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type Image struct {
|
||||||
|
}
|
||||||
|
|
||||||
type PostThumbnail struct {
|
type PostThumbnail struct {
|
||||||
Path string
|
Path string
|
||||||
Width int
|
Width int
|
||||||
Height int
|
Height int
|
||||||
Srcset string
|
Srcset string
|
||||||
Sizes string
|
Sizes string
|
||||||
|
OriginAttachmentData WpAttachmentMetadata
|
||||||
}
|
}
|
||||||
|
|
||||||
func (w Posts) PrimaryKey() string {
|
func (w Posts) PrimaryKey() string {
|
||||||
|
@ -52,6 +52,7 @@ func Hook(status int, c *gin.Context, h gin.H, scene, stats int) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else if scene == plugins.Detail {
|
} else if scene == plugins.Detail {
|
||||||
|
h["HeaderImage"] = getHeaderImage(c)
|
||||||
templ = "twentyseventeen/posts/detail.gohtml"
|
templ = "twentyseventeen/posts/detail.gohtml"
|
||||||
}
|
}
|
||||||
c.HTML(status, templ, h)
|
c.HTML(status, templ, h)
|
||||||
|
@ -3,7 +3,6 @@ package model
|
|||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
"database/sql"
|
"database/sql"
|
||||||
"github.com/fthvgb1/wp-go/helper"
|
|
||||||
"github.com/fthvgb1/wp-go/helper/number"
|
"github.com/fthvgb1/wp-go/helper/number"
|
||||||
"github.com/fthvgb1/wp-go/helper/slice"
|
"github.com/fthvgb1/wp-go/helper/slice"
|
||||||
_ "github.com/go-sql-driver/mysql"
|
_ "github.com/go-sql-driver/mysql"
|
||||||
@ -499,10 +498,10 @@ func TestSimplePagination(t *testing.T) {
|
|||||||
order: nil,
|
order: nil,
|
||||||
join: nil,
|
join: nil,
|
||||||
having: nil,
|
having: nil,
|
||||||
in: [][]any{slice.Map[int, any](number.Range(431, 440, 1), helper.ToAny[int])},
|
in: [][]any{slice.ToAnySlice(number.Range(431, 440, 1))},
|
||||||
},
|
},
|
||||||
wantR: func() (r []post) {
|
wantR: func() (r []post) {
|
||||||
r, err := Select[post](ctx, "select * from "+post{}.Table()+" where ID in (?,?,?,?,?)", slice.Map[int, any](number.Range(431, 435, 1), helper.ToAny[int])...)
|
r, err := Select[post](ctx, "select * from "+post{}.Table()+" where ID in (?,?,?,?,?)", slice.ToAnySlice(number.Range(431, 435, 1))...)
|
||||||
if err != nil && err != sql.ErrNoRows {
|
if err != nil && err != sql.ErrNoRows {
|
||||||
panic(err)
|
panic(err)
|
||||||
} else if err == sql.ErrNoRows {
|
} else if err == sql.ErrNoRows {
|
||||||
|
@ -17,6 +17,22 @@ type MultipleFsTemplate struct {
|
|||||||
Fs embed.FS
|
Fs embed.FS
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (t *MultipleFileTemplate) AppendTemplate(name string, templates ...string) *MultipleFileTemplate {
|
||||||
|
tmpl, ok := t.Template[name]
|
||||||
|
if ok {
|
||||||
|
t.Template[name] = template.Must(tmpl.ParseFiles(templates...))
|
||||||
|
}
|
||||||
|
return t
|
||||||
|
}
|
||||||
|
|
||||||
|
func (t *MultipleFsTemplate) AppendTemplate(name string, templates ...string) *MultipleFsTemplate {
|
||||||
|
tmpl, ok := t.Template[name]
|
||||||
|
if ok {
|
||||||
|
t.Template[name] = template.Must(tmpl.ParseFS(t.Fs, templates...))
|
||||||
|
}
|
||||||
|
return t
|
||||||
|
}
|
||||||
|
|
||||||
func NewFileTemplate() *MultipleFileTemplate {
|
func NewFileTemplate() *MultipleFileTemplate {
|
||||||
return &MultipleFileTemplate{
|
return &MultipleFileTemplate{
|
||||||
Template: make(map[string]*template.Template),
|
Template: make(map[string]*template.Template),
|
||||||
@ -47,9 +63,6 @@ func (t *MultipleFileTemplate) AddTemplate(mainTemplatePattern string, fnMap tem
|
|||||||
panic(err)
|
panic(err)
|
||||||
}
|
}
|
||||||
for _, mainTemplate := range mainTemplates {
|
for _, mainTemplate := range mainTemplates {
|
||||||
if _, ok := t.Template[mainTemplate]; ok {
|
|
||||||
panic("exists same Template " + mainTemplate)
|
|
||||||
}
|
|
||||||
file := filepath.Base(mainTemplate)
|
file := filepath.Base(mainTemplate)
|
||||||
pattern := append([]string{mainTemplate}, layoutTemplatePattern...)
|
pattern := append([]string{mainTemplate}, layoutTemplatePattern...)
|
||||||
t.Template[mainTemplate] = template.Must(template.New(file).Funcs(fnMap).ParseFiles(pattern...))
|
t.Template[mainTemplate] = template.Must(template.New(file).Funcs(fnMap).ParseFiles(pattern...))
|
||||||
|
Loading…
Reference in New Issue
Block a user