-
Fetch up to page:
- {{range .PageNums}}
+
+ {{if gt .TotalPages 1}}
+
+
+
Page:
+ {{$cur := .CurrentPage}}
+ {{range .DisplayNums}}
{{if eq .Num 0}}
…
+ {{else if eq .Num $cur}}
+
{{.Num}}
{{else}}
-
+
+ {{.Num}}
+
{{end}}
{{end}}
-
- Each page = ~20 novels from
- novelfire.net popular
-
+
Showing {{.TotalItems}} cached novels · page {{.CurrentPage}} of {{.TotalPages}}
+ {{end}}
+
+
+
+
+
+ Fetch more from novelfire.net
+
+
+
+ Fetch up to page:
+ {{range .FetchNums}}
+ {{if eq .Num 0}}
+ …
+ {{else}}
+
+ {{end}}
+ {{end}}
+
+
+ Each page ≈ 20 novels from
+ novelfire.net popular
+
+
+
@@ -777,8 +810,11 @@ func rankingPageNums(total int) []pageNum {
return out
}
-// handleRanking serves the ranking page from the cached ranking.md file.
+const rankingPageSize = 20
+
+// handleRanking serves the ranking page from the cached ranking.json file.
// It does NOT trigger a live scrape; use POST /ranking/refresh for that.
+// Supports ?page=N for browsing through cached items (20 per page).
func (s *Server) handleRanking(w http.ResponseWriter, r *http.Request) {
rankingItems, err := s.writer.ReadRankingItems()
if err != nil {
@@ -790,16 +826,52 @@ func (s *Server) handleRanking(w http.ResponseWriter, r *http.Request) {
cachedAt = info.ModTime().Format("Jan 2, 2006 at 15:04")
}
+ // Parse requested display page (1-indexed).
+ currentPage := 1
+ if p := r.URL.Query().Get("page"); p != "" {
+ if n, err2 := strconv.Atoi(p); err2 == nil && n > 0 {
+ currentPage = n
+ }
+ }
+
+ totalItems := len(rankingItems)
+ totalPages := 1
+ if totalItems > 0 {
+ totalPages = (totalItems + rankingPageSize - 1) / rankingPageSize
+ }
+ if currentPage > totalPages {
+ currentPage = totalPages
+ }
+
+ // Slice items for the current display page.
+ start := (currentPage - 1) * rankingPageSize
+ end := start + rankingPageSize
+ if end > totalItems {
+ end = totalItems
+ }
+ pageItems := rankingItems
+ if totalItems > 0 {
+ pageItems = rankingItems[start:end]
+ }
+
t := template.Must(template.New("ranking").Parse(rankingTmpl))
var buf bytes.Buffer
_ = t.Execute(&buf, struct {
- Books interface{}
- CachedAt string
- PageNums []pageNum
+ Books interface{}
+ CachedAt string
+ FetchNums []pageNum
+ DisplayNums []pageNum
+ CurrentPage int
+ TotalPages int
+ TotalItems int
}{
- Books: toRankingViewItems(rankingItems, s.writer.LocalSlugs()),
- CachedAt: cachedAt,
- PageNums: rankingPageNums(100),
+ Books: toRankingViewItems(pageItems, s.writer.LocalSlugs()),
+ CachedAt: cachedAt,
+ FetchNums: rankingPageNums(100),
+ DisplayNums: rankingPageNums(totalPages),
+ CurrentPage: currentPage,
+ TotalPages: totalPages,
+ TotalItems: totalItems,
})
s.respond(w, r, "Rankings", buf.String())
}