package page import ( "bytes" "encoding/json" "errors" "io/fs" "net/http" "path/filepath" ) // RenderJson is analogous to Render, though it renders the page, // as a JSON key "content", optionally from the YAML it'll include // additional keys in the json if specified under the 'pageJson' key. // E.g. // --- // title: Some page // description: Some page desc // jsonvars: // - includeMeInJSON // vars: // notIncluded: some value // includeMeInJSON: // some: arbitrary // data: to // send: down // |-- // My page content, wee! func RenderJson(w http.ResponseWriter, r *http.Request, path string, vars map[string]interface{}, statusCode int) { u := getURLPath(r) u = filepath.Join(".", u) // Sepcifically use the specified path for the page p := NewPage(path) if vars != nil { p.Vars = vars } out := map[string]interface{}{} buf := &bytes.Buffer{} err := p.Render(buf) if err != nil { if errors.Is(err, fs.ErrNotExist) { renderJsonErr(w, r, "Not found", http.StatusNotFound) return } Logger.Printf("%s %s path: %s rendering encountered: %s", r.RemoteAddr, r.Method, u, err) renderJsonErr(w, r, "Internal server error", http.StatusInternalServerError) return } if r.URL.Query().Get("content") == "1" { out["Content"] = buf.String() } if r.URL.Query().Get("markdown") == "1" { // Tossing the error, since it would've been revealed above md, _ := p.GetMarkdown() out["Markdown"] = md } // Make a "set" of keys keys := map[string]struct{}{} for _, k := range p.JsonVars { keys[k] = struct{}{} } // And chuck the keys specified into the output for k, v := range p.Vars { _, ok := keys[k] if ok { out[k] = v } } w.WriteHeader(statusCode) enc := json.NewEncoder(w) enc.SetIndent("", " ") enc.SetEscapeHTML(false) err = enc.Encode(out) if err != nil { Logger.Printf("%s %s %d %s: while writing buf: %s", r.RemoteAddr, r.Method, statusCode, u, err) return } Logger.Printf("%s %s %d %s", r.RemoteAddr, r.Method, statusCode, u) } func renderJsonErr(w http.ResponseWriter, r *http.Request, msg string, statusCode int) { enc := json.NewEncoder(w) w.WriteHeader(statusCode) _ = enc.Encode(&struct { Status string }{ Status: msg, }) }