feat: switch ranking storage from markdown to JSON, fix round-trip test
Some checks failed
CI / Lint (push) Has been cancelled
CI / Test (push) Has been cancelled
CI / Build (push) Has been cancelled

- WriteRanking now writes ranking.json via json.MarshalIndent (replaces markdown table)
- ReadRankingItems uses json.Unmarshal (no fragile pipe-split parsing)
- ReadRanking() (raw string reader) removed; handleRankingView uses ReadRankingItems
- handleRankingView renders a <pre> JSON block instead of goldmark markdown
- RankingItem gains json: struct tags; slug and genres now survive the round-trip exactly
- TestWriteRanking_RoundTrip updated: checks ranking.json, verifies Slug/Genres/SourceURL
- Add RankingPageCacher interface and per-page HTML disk cache support in scraper
This commit is contained in:
Admin
2026-03-01 21:44:39 +05:00
parent 0521ef11ee
commit 0aba23de1f
3 changed files with 51 additions and 110 deletions

View File

@@ -933,31 +933,29 @@ const rankingViewTmpl = `
<h1 class="text-3xl font-bold text-zinc-100 mb-6">Ranking Data</h1>
<div class="prose prose-invert max-w-none">
{{.HTML}}
</div>
<pre class="text-xs text-zinc-300 bg-zinc-900 border border-zinc-700 rounded-xl p-4 overflow-x-auto whitespace-pre-wrap break-words">{{.JSON}}</pre>
</div>`
func (s *Server) handleRankingView(w http.ResponseWriter, r *http.Request) {
markdown, err := s.writer.ReadRanking()
items, err := s.writer.ReadRankingItems()
if err != nil {
http.Error(w, "failed to read ranking: "+err.Error(), http.StatusInternalServerError)
return
}
if markdown == "" {
if len(items) == 0 {
http.NotFound(w, r)
return
}
var htmlBuf bytes.Buffer
if err := md.Convert([]byte(markdown), &htmlBuf); err != nil {
http.Error(w, "markdown render error: "+err.Error(), http.StatusInternalServerError)
pretty, err := json.MarshalIndent(items, "", " ")
if err != nil {
http.Error(w, "json marshal error: "+err.Error(), http.StatusInternalServerError)
return
}
t := template.Must(template.New("rankingView").Parse(rankingViewTmpl))
var buf bytes.Buffer
_ = t.Execute(&buf, struct{ HTML template.HTML }{HTML: template.HTML(htmlBuf.String())})
_ = t.Execute(&buf, struct{ JSON string }{JSON: string(pretty)})
s.respond(w, r, "Ranking Data", buf.String())
}