Sergiusz Bazanski | c881cf3 | 2020-04-08 20:03:12 +0200 | [diff] [blame] | 1 | package main |
| 2 | |
| 3 | import ( |
Sergiusz Bazanski | f157b4d | 2020-04-10 17:39:43 +0200 | [diff] [blame^] | 4 | "bytes" |
Sergiusz Bazanski | c881cf3 | 2020-04-08 20:03:12 +0200 | [diff] [blame] | 5 | "html/template" |
Sergiusz Bazanski | f157b4d | 2020-04-10 17:39:43 +0200 | [diff] [blame^] | 6 | "net/url" |
Sergiusz Bazanski | c881cf3 | 2020-04-08 20:03:12 +0200 | [diff] [blame] | 7 | "strings" |
| 8 | |
| 9 | "code.hackerspace.pl/hscloud/devtools/hackdoc/config" |
Sergiusz Bazanski | c881cf3 | 2020-04-08 20:03:12 +0200 | [diff] [blame] | 10 | |
| 11 | "github.com/golang/glog" |
| 12 | "gopkg.in/russross/blackfriday.v2" |
| 13 | ) |
| 14 | |
Sergiusz Bazanski | f157b4d | 2020-04-10 17:39:43 +0200 | [diff] [blame^] | 15 | // renderMarkdown renders markdown to HTML, replacing all relative (intra-hackdoc) links with version that have ref set. |
| 16 | func renderMarkdown(input []byte, ref string) []byte { |
| 17 | r := blackfriday.NewHTMLRenderer(blackfriday.HTMLRendererParameters{ |
| 18 | Flags: blackfriday.CommonHTMLFlags, |
| 19 | }) |
| 20 | |
| 21 | parser := blackfriday.New(blackfriday.WithRenderer(r), blackfriday.WithExtensions(blackfriday.CommonExtensions)) |
| 22 | ast := parser.Parse(input) |
| 23 | |
| 24 | var buf bytes.Buffer |
| 25 | ast.Walk(func(node *blackfriday.Node, entering bool) blackfriday.WalkStatus { |
| 26 | if ref != "" && entering && node.Type == blackfriday.Link { |
| 27 | dest := string(node.Destination) |
| 28 | u, err := url.Parse(dest) |
| 29 | if err == nil && !u.IsAbs() { |
| 30 | q := u.Query() |
| 31 | q["ref"] = []string{ref} |
| 32 | u.RawQuery = q.Encode() |
| 33 | node.Destination = []byte(u.String()) |
| 34 | } |
| 35 | } |
| 36 | return r.RenderNode(&buf, node, entering) |
| 37 | }) |
| 38 | return buf.Bytes() |
| 39 | } |
| 40 | |
| 41 | func (r *request) handleMarkdown(path string, cfg *config.Config) { |
| 42 | data, err := r.source.ReadFile(r.ctx, path) |
Sergiusz Bazanski | c881cf3 | 2020-04-08 20:03:12 +0200 | [diff] [blame] | 43 | if err != nil { |
| 44 | glog.Errorf("ReadFile(%q): %w", err) |
Sergiusz Bazanski | f157b4d | 2020-04-10 17:39:43 +0200 | [diff] [blame^] | 45 | r.handle500() |
Sergiusz Bazanski | c881cf3 | 2020-04-08 20:03:12 +0200 | [diff] [blame] | 46 | return |
| 47 | } |
| 48 | |
Sergiusz Bazanski | f157b4d | 2020-04-10 17:39:43 +0200 | [diff] [blame^] | 49 | rendered := renderMarkdown([]byte(data), r.ref) |
Sergiusz Bazanski | c881cf3 | 2020-04-08 20:03:12 +0200 | [diff] [blame] | 50 | |
Sergiusz Bazanski | f157b4d | 2020-04-10 17:39:43 +0200 | [diff] [blame^] | 51 | r.logRequest("serving markdown at %s, cfg %+v", path, cfg) |
Sergiusz Bazanski | c881cf3 | 2020-04-08 20:03:12 +0200 | [diff] [blame] | 52 | |
| 53 | // TODO(q3k): allow markdown files to override which template to load |
| 54 | tmpl, ok := cfg.Templates["default"] |
| 55 | if !ok { |
| 56 | glog.Errorf("No default template found for %s", path) |
| 57 | // TODO(q3k): implement fallback template |
Sergiusz Bazanski | f157b4d | 2020-04-10 17:39:43 +0200 | [diff] [blame^] | 58 | r.w.Write(rendered) |
Sergiusz Bazanski | c881cf3 | 2020-04-08 20:03:12 +0200 | [diff] [blame] | 59 | return |
| 60 | } |
| 61 | |
Sergiusz Bazanski | f157b4d | 2020-04-10 17:39:43 +0200 | [diff] [blame^] | 62 | pathInDepot := strings.TrimPrefix(path, "//") |
Sergiusz Bazanski | c881cf3 | 2020-04-08 20:03:12 +0200 | [diff] [blame] | 63 | vars := map[string]interface{}{ |
| 64 | "Rendered": template.HTML(rendered), |
| 65 | "Title": path, |
| 66 | "Path": path, |
Sergiusz Bazanski | f157b4d | 2020-04-10 17:39:43 +0200 | [diff] [blame^] | 67 | "PathInDepot": pathInDepot, |
Sergiusz Bazanski | c881cf3 | 2020-04-08 20:03:12 +0200 | [diff] [blame] | 68 | "HackdocURL": flagHackdocURL, |
Sergiusz Bazanski | f157b4d | 2020-04-10 17:39:43 +0200 | [diff] [blame^] | 69 | "WebLinks": r.source.WebLinks(pathInDepot), |
Sergiusz Bazanski | c881cf3 | 2020-04-08 20:03:12 +0200 | [diff] [blame] | 70 | } |
Sergiusz Bazanski | f157b4d | 2020-04-10 17:39:43 +0200 | [diff] [blame^] | 71 | err = tmpl.Execute(r.w, vars) |
Sergiusz Bazanski | c881cf3 | 2020-04-08 20:03:12 +0200 | [diff] [blame] | 72 | if err != nil { |
| 73 | glog.Errorf("Could not execute template for %s: %v", err) |
| 74 | } |
| 75 | } |