package models_pages
import (
"bytes"
"fmt"
"html/template"
"log"
"main/tools"
"os"
"path/filepath"
"sort"
"strconv"
"strings"
"time"
)
const (
// Имя соответствующего шаблона
PostsPageTmplName = "posts.gohtml"
)
type PostsMap map[PostLink]*Post
type PostsPage struct {
PostsListOnPage []*Post // список постов на странице
PageNumber int // номер страницы
PagesCount int // общее количество страниц
}
func LoadPosts(dir string) (PostsMap, error) {
posts := PostsMap{}
err := filepath.Walk(dir, func(path string, f os.FileInfo, err error) error {
if err != nil {
return err
}
if !f.IsDir() && strings.HasSuffix(f.Name(), ".md") {
md, err := os.ReadFile(path)
if err != nil {
return err
}
html := tools.MdToHTML(md)
name := filepath.Base(path)
lowLineIndex := strings.Index(name, "_")
if lowLineIndex == -1 {
// Обработка случая, если "_" нет в имени
log.Fatal(`post name parse error`)
}
timestampStr := name[:lowLineIndex]
timestamp, err := strconv.ParseInt(timestampStr, 10, 64)
if err != nil {
// Ошибка парсинга timestamp
log.Fatal(`post name parse error`)
}
link := fmt.Sprintf("/%s", strings.TrimSuffix(name[lowLineIndex+1:], ".md"))
posts[PostLink(link)] = createPost(link, html, timestamp)
}
return nil
})
if err != nil {
return nil, err
}
return posts, nil
}
// Получение из мапы постов списка постов, отсортированного по ModTimestamp (новые сначала)
func (p *PostsMap) PostsList() []*Post {
postsSlice := make([]*Post, 0, len(*p))
for _, post := range *p {
postsSlice = append(postsSlice, post)
}
sort.Slice(postsSlice, func(i, j int) bool {
return postsSlice[i].Timestamp > postsSlice[j].Timestamp
})
return postsSlice
}
func CreatePage(postsList []*Post, pageNumber, postsMaxCountOnPage int) *PostsPage {
// Общее количество страниц
pagesCount := (len(postsList) + postsMaxCountOnPage - 1) / postsMaxCountOnPage
// Ошибки тут быть не может, так как этот обработчик настроен
// на только существующие реально pageNumber и в случае
// какого то не существующего номера страницы он просто
// не сработает (в главном main настроены маршруты)
startIndex := pageNumber * postsMaxCountOnPage
endIndex := startIndex + postsMaxCountOnPage
endIndex = min(endIndex, len(postsList))
postsSublistForPageNumber := postsList[startIndex:endIndex]
return &PostsPage{
PostsListOnPage: postsSublistForPageNumber,
PageNumber: pageNumber,
PagesCount: pagesCount,
}
}
func (p *PostsPage) RenderPostsPage(templates *template.Template, version int64) ([]byte, error) {
var pageData bytes.Buffer
var prevPageNumber, nextPageNumber int
if p.PageNumber == 0 {
prevPageNumber = p.PagesCount - 1
} else {
prevPageNumber = p.PageNumber - 1
}
nextPageNumber = (p.PageNumber + 1) % p.PagesCount
pagi := fmt.Sprintf(
`<- %d/%d ->`,
prevPageNumber,
p.PageNumber+1,
p.PagesCount,
nextPageNumber,
)
context := map[string]any{
"pagi": template.HTML(pagi),
"version": version,
"renderingTimestamp": time.Now().Unix(),
"posts": p.PostsListOnPage,
}
if err := templates.ExecuteTemplate(&pageData, PostsPageTmplName, context); err != nil {
return nil, err
}
return pageData.Bytes(), nil
}