Files
himewiki/internal/action/edit.go

214 lines
5.0 KiB
Go

package action
import (
"html/template"
"net/http"
"net/url"
"strconv"
"strings"
"golang.org/x/text/unicode/norm"
"tea.kareha.org/pot/himewiki/internal/config"
"tea.kareha.org/pot/himewiki/internal/data"
"tea.kareha.org/pot/himewiki/internal/filter"
"tea.kareha.org/pot/himewiki/internal/format"
"tea.kareha.org/pot/himewiki/internal/templates"
"tea.kareha.org/pot/himewiki/internal/util"
)
func View(cfg *config.Config, w http.ResponseWriter, r *http.Request, params *Params) {
_, content, err := data.Load(params.DbName)
if err != nil {
http.Redirect(w, r, "/"+url.PathEscape(params.Name)+"?a=edit", http.StatusFound)
return
}
title, _, plain, rendered := format.Apply(cfg, params.DbName, content)
summary := format.TrimForSummary(plain, 144)
subAction := r.URL.Query().Get("b")
diffText := ""
if subAction == "diff" {
_, prev, _ := data.LoadPrev(params.DbName)
diffText = util.Diff(prev, content)
}
searchName := params.Name
if strings.HasSuffix(searchName, ".wiki") {
searchName = searchName[:len(searchName)-5]
}
data := struct {
Base string
SiteName string
Card string
Name string
Summary string
Title string
SearchName string
Rendered template.HTML
Diff string
}{
Base: cfg.Site.Base,
SiteName: cfg.Site.Name,
Card: cfg.Site.Card,
Name: params.Name,
Summary: summary,
Title: title,
SearchName: searchName,
Rendered: template.HTML(rendered),
Diff: diffText,
}
templates.Render(w, "view", data)
}
func Edit(cfg *config.Config, w http.ResponseWriter, r *http.Request, params *Params) {
var previewed bool
var revisionID int
var content string
var preview string
var save string
if r.Method != http.MethodPost {
previewed = false
revisionID, content, _ = data.Load(params.DbName)
preview = ""
save = ""
} else {
previewed = r.FormValue("previewed") == "true"
var err error
revisionID, err = strconv.Atoi(r.FormValue("revision_id"))
if err != nil || revisionID < 0 {
http.Error(w, "Invalid revision ID", http.StatusInternalServerError)
return
}
rawContent := r.FormValue("content")
content = norm.NFC.String(rawContent)
preview = r.FormValue("preview")
save = r.FormValue("save")
}
var filtered string
var err error
if previewed && save != "" {
filtered, err = filter.Apply(cfg, params.DbName, content)
} else {
filtered, err = content, nil
}
if err != nil {
http.Error(w, "Failed to filter content", http.StatusInternalServerError)
return
}
title, normalized, _, rendered := format.Apply(cfg, params.DbName, filtered)
diffText := ""
if previewed && save != "" {
pageCount, err := data.Save(cfg, params.DbName, normalized, revisionID)
if err != nil {
http.Error(w, "Failed to save", http.StatusInternalServerError)
return
}
if cfg.Gnome.Agent != "nil" {
if pageCount%int64(cfg.Gnome.Ratio) == 0 {
targetRecent := (pageCount / int64(cfg.Gnome.Ratio)) % int64(cfg.Gnome.Recent)
go func() {
runGnome(cfg, int(targetRecent))
}()
}
}
http.Redirect(w, r, "/"+url.PathEscape(params.Name)+"?b=diff", http.StatusFound)
return
} else if preview != "" {
previewed = true
_, current, _ := data.Load(params.DbName)
diffText = util.Diff(current, normalized)
}
searchName := params.Name
if strings.HasSuffix(searchName, ".wiki") {
searchName = searchName[:len(searchName)-5]
}
w.Header().Set("Cache-Control", "no-store")
w.Header().Set("Pragma", "no-cache")
data := struct {
SiteName string
Name string
Previewed bool
RevisionID int
Text string
Title string
SearchName string
Rendered template.HTML
Diff string
}{
SiteName: cfg.Site.Name,
Name: params.Name,
Previewed: previewed,
RevisionID: revisionID,
Text: normalized,
Title: title,
SearchName: searchName,
Rendered: template.HTML(rendered),
Diff: diffText,
}
templates.Render(w, "edit", data)
}
const perBigPage = 500
func All(cfg *config.Config, w http.ResponseWriter, r *http.Request, params *Params) {
pageStr := r.URL.Query().Get("p")
page, err := strconv.Atoi(pageStr)
if err != nil {
page = 1
}
pages, err := data.LoadAll(page, perBigPage)
if err != nil {
http.Error(w, "Failed to load pages", http.StatusInternalServerError)
return
}
data := struct {
SiteName string
Pages []string
NextPage int
}{
SiteName: cfg.Site.Name,
Pages: pages,
NextPage: page + 1,
}
templates.Render(w, "all", data)
}
const perPage = 50
func Recent(cfg *config.Config, w http.ResponseWriter, r *http.Request, params *Params) {
pageStr := r.URL.Query().Get("p")
page, err := strconv.Atoi(pageStr)
if err != nil {
page = 1
}
records, err := data.Recent(page, perPage)
if err != nil {
http.Error(w, "Failed to load pages", http.StatusInternalServerError)
return
}
data := struct {
SiteName string
Records []data.RecentRecord
NextPage int
}{
SiteName: cfg.Site.Name,
Records: records,
NextPage: page + 1,
}
templates.Render(w, "recent", data)
}