Added additional filters

Author Mitja Felicijan <mitja.felicijan@gmail.com> 2024-06-21 17:28:03 +0200
Committer Mitja Felicijan <mitja.felicijan@gmail.com> 2024-06-21 17:28:03 +0200
Commit 0130404a1dc663d4aa68d780c9bcb23a4243e68d (patch)
-rw-r--r-- README.md 21
-rw-r--r-- filters.go 69
-rw-r--r-- main.go 65
3 files changed, 96 insertions, 59 deletions
diff --git a/README.md b/README.md
...
163
- first (gets first N posts)
163
- first (gets first N posts)
164
- last (gets last N posts)
164
- last (gets last N posts)
165
- random (gets random N posts)
165
- random (gets random N posts)
  
166
- filterbytype (get just the posts with specific type)
166
  
167
  
167
```html
168
```html
168
<!-- First 10 pages -->
169
<!-- First 10 pages -->
169
{{ range first 10 .Pages }}
170
{{ range .Pages | first 10 }}
170
  {{ if and (eq .Type "post") (not .Draft) }}
171
  {{ if and (eq .Type "post") (not .Draft) }}
171
    <li><a href="{{ .RelPermalink }}">{{ .Title }}</a></li>
172
    <li><a href="{{ .RelPermalink }}">{{ .Title }}</a></li>
172
  {{ end }}
173
  {{ end }}
173
{{ end }}
174
{{ end }}
174
  
175
  
175
<!-- Last 10 pages -->
176
<!-- Last 10 pages -->
176
{{ range last 10 .Pages }}
177
{{ range .Pages | last 10 }}
177
  {{ if and (eq .Type "post") (not .Draft) }}
178
  {{ if and (eq .Type "post") (not .Draft) }}
178
    <li><a href="{{ .RelPermalink }}">{{ .Title }}</a></li>
179
    <li><a href="{{ .RelPermalink }}">{{ .Title }}</a></li>
179
  {{ end }}
180
  {{ end }}
180
{{ end }}
181
{{ end }}
181
  
182
  
182
<!-- Random 10 pages -->
183
<!-- Random 10 pages -->
183
{{ range random 10 .Pages }}
184
{{ range .Pages | random 10 }}
184
  {{ if and (eq .Type "post") (not .Draft) }}
185
  {{ if and (eq .Type "post") (not .Draft) }}
  
186
    <li><a href="{{ .RelPermalink }}">{{ .Title }}</a></li>
  
187
  {{ end }}
  
188
{{ end }}
  
189
  
  
190
<!-- Filter by type -->
  
191
{{ range .Pages | filterbytype "post" }}
  
192
  {{ if not .Draft }}
  
193
    <li><a href="{{ .RelPermalink }}">{{ .Title }}</a></li>
  
194
  {{ end }}
  
195
{{ end }}
  
196
  
  
197
<!-- Chain multiple together -->
  
198
{{ range .Pages | filterbytype "post" | random 20 | first 5 }}
  
199
  {{ if not .Draft }}
185
    <li><a href="{{ .RelPermalink }}">{{ .Title }}</a></li>
200
    <li><a href="{{ .RelPermalink }}">{{ .Title }}</a></li>
186
  {{ end }}
201
  {{ end }}
187
{{ end }}
202
{{ end }}
...
diff --git a/filters.go b/filters.go
  
1
package main
  
2
  
  
3
import (
  
4
	"math/rand"
  
5
	"reflect"
  
6
	"time"
  
7
)
  
8
  
  
9
// firstN returns the first n items of a slice.
  
10
func firstN(n int, items interface{}) interface{} {
  
11
	v := reflect.ValueOf(items)
  
12
	if v.Kind() != reflect.Slice {
  
13
		panic("firstN: not a slice")
  
14
	}
  
15
	if v.Len() < n {
  
16
		return items
  
17
	}
  
18
	return v.Slice(0, n).Interface()
  
19
}
  
20
  
  
21
// lastN returns the last n items of any slice.
  
22
func lastN(n int, items interface{}) interface{} {
  
23
	v := reflect.ValueOf(items)
  
24
	if v.Kind() != reflect.Slice {
  
25
		panic("lastN: not a slice")
  
26
	}
  
27
	l := v.Len()
  
28
	if l < n {
  
29
		return items
  
30
	}
  
31
	return v.Slice(l-n, l).Interface()
  
32
}
  
33
  
  
34
// randomN returns n random items of any slice.
  
35
func randomN(n int, items interface{}) interface{} {
  
36
	v := reflect.ValueOf(items)
  
37
	if v.Kind() != reflect.Slice {
  
38
		panic("randomN: not a slice")
  
39
	}
  
40
	l := v.Len()
  
41
	if l < n {
  
42
		return items
  
43
	}
  
44
	rand.Seed(time.Now().UnixNano())
  
45
	indices := rand.Perm(l)[:n]
  
46
	result := reflect.MakeSlice(v.Type(), n, n)
  
47
	for i, idx := range indices {
  
48
		result.Index(i).Set(v.Index(idx))
  
49
	}
  
50
	return result.Interface()
  
51
}
  
52
  
  
53
// filterByType filters pages by their type.
  
54
func filterByType(pageType string, pages interface{}) interface{} {
  
55
	v := reflect.ValueOf(pages)
  
56
	if v.Kind() != reflect.Slice {
  
57
		panic("filterByType: not a slice")
  
58
	}
  
59
  
  
60
	var filtered []interface{}
  
61
	for i := 0; i < v.Len(); i++ {
  
62
		page := v.Index(i).Interface().(Page)
  
63
		if page.Type == pageType {
  
64
			filtered = append(filtered, page)
  
65
		}
  
66
	}
  
67
	return filtered
  
68
}
  
69
  
diff --git a/main.go b/main.go
...
5
	"fmt"
5
	"fmt"
6
	"html/template"
6
	"html/template"
7
	"log"
7
	"log"
8
	"math/rand"
  
9
	"net/http"
8
	"net/http"
10
	"os"
9
	"os"
11
	"path"
10
	"path"
12
	"path/filepath"
11
	"path/filepath"
13
	"reflect"
  
14
	"sort"
12
	"sort"
15
	"strings"
13
	"strings"
16
	"time"
14
	"time"
...
89
//go:embed "files/index.xml"
87
//go:embed "files/index.xml"
90
var EmbedTemplateFeed string
88
var EmbedTemplateFeed string
91
  
89
  
92
// firstN returns the first n items of a slice.
  
93
func firstN(n int, items interface{}) interface{} {
  
94
	v := reflect.ValueOf(items)
  
95
	if v.Kind() != reflect.Slice {
  
96
		panic("firstN: not a slice")
  
97
	}
  
98
	if v.Len() < n {
  
99
		return items
  
100
	}
  
101
	return v.Slice(0, n).Interface()
  
102
}
  
103
  
  
104
// lastN returns the last n items of any slice.
  
105
func lastN(n int, items interface{}) interface{} {
  
106
	v := reflect.ValueOf(items)
  
107
	if v.Kind() != reflect.Slice {
  
108
		panic("lastN: not a slice")
  
109
	}
  
110
	l := v.Len()
  
111
	if l < n {
  
112
		return items
  
113
	}
  
114
	return v.Slice(l-n, l).Interface()
  
115
}
  
116
  
  
117
// randomN returns n random items of any slice.
  
118
func randomN(n int, items interface{}) interface{} {
  
119
	v := reflect.ValueOf(items)
  
120
	if v.Kind() != reflect.Slice {
  
121
		panic("randomN: not a slice")
  
122
	}
  
123
	l := v.Len()
  
124
	if l < n {
  
125
		return items
  
126
	}
  
127
	rand.Seed(time.Now().UnixNano())
  
128
	indices := rand.Perm(l)[:n]
  
129
	result := reflect.MakeSlice(v.Type(), n, n)
  
130
	for i, idx := range indices {
  
131
		result.Index(i).Set(v.Index(idx))
  
132
	}
  
133
	return result.Interface()
  
134
}
  
135
  
  
136
// Function to clean HTML tags using bluemonday.
90
// Function to clean HTML tags using bluemonday.
137
func cleanHTMLTags(htmlString string) string {
91
func cleanHTMLTags(htmlString string) string {
138
	p := bluemonday.StrictPolicy()
92
	p := bluemonday.StrictPolicy()
...
318
		return
272
		return
319
	}
273
	}
320
  
274
  
  
275
	filters := template.FuncMap{
  
276
		"first":  firstN,
  
277
		"last":   lastN,
  
278
		"random": randomN,
  
279
		"filterbytype": filterByType,
  
280
	}
  
281
  
321
	// Generate HTML files for all pages.
282
	// Generate HTML files for all pages.
322
	for _, page := range pages {
283
	for _, page := range pages {
323
		outFilepath := path.Join(projectRoot, "public", page.Meta["url"].(string))
284
		outFilepath := path.Join(projectRoot, "public", page.Meta["url"].(string))
...
330
			templates = append([]string{templatePathname}, templates...)
291
			templates = append([]string{templatePathname}, templates...)
331
			templates = append([]string{baseTemplatePathname}, templates...)
292
			templates = append([]string{baseTemplatePathname}, templates...)
332
  
293
  
333
			t, err := template.New("base.html").Funcs(template.FuncMap{
294
			t, err := template.New("base.html").Funcs(filters).ParseFiles(templates...)
334
				"first":  firstN,
  
335
				"last":   lastN,
  
336
				"random": randomN,
  
337
			}).ParseFiles(templates...)
  
338
			if err != nil {
295
			if err != nil {
339
				panic(err)
296
				panic(err)
340
			}
297
			}
...
385
		templates = append([]string{templatePathname}, templates...)
342
		templates = append([]string{templatePathname}, templates...)
386
		templates = append([]string{baseTemplatePathname}, templates...)
343
		templates = append([]string{baseTemplatePathname}, templates...)
387
  
344
  
388
		t, err := template.New("base.html").Funcs(template.FuncMap{
345
		t, err := template.New("base.html").Funcs(filters).ParseFiles(templates...)
389
			"first":  firstN,
  
390
			"last":   lastN,
  
391
			"random": randomN,
  
392
		}).ParseFiles(templates...)
  
393
		if err != nil {
346
		if err != nil {
394
			panic(err)
347
			panic(err)
395
		}
348
		}
...