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( `<-  ->`, prevPageNumber, 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 }