mirror of
https://github.com/golang/go
synced 2024-11-18 10:54:40 -07:00
present: add OldURL metadata and use for redirects in blog
This will allow renaming blog pages to have shorter, more easily typed URLs, while keeping the old links working. Change-Id: I2cd6733eaaf02a4b8e73afc773173c655d317ee6 Reviewed-on: https://go-review.googlesource.com/c/tools/+/223603 Reviewed-by: Andrew Bonventre <andybons@golang.org>
This commit is contained in:
parent
cf1dd6fc34
commit
b304dfc3e0
36
blog/blog.go
36
blog/blog.go
@ -65,12 +65,13 @@ type Doc struct {
|
||||
|
||||
// Server implements an http.Handler that serves blog articles.
|
||||
type Server struct {
|
||||
cfg Config
|
||||
docs []*Doc
|
||||
tags []string
|
||||
docPaths map[string]*Doc // key is path without BasePath.
|
||||
docTags map[string][]*Doc
|
||||
template struct {
|
||||
cfg Config
|
||||
docs []*Doc
|
||||
redirects map[string]string
|
||||
tags []string
|
||||
docPaths map[string]*Doc // key is path without BasePath.
|
||||
docTags map[string][]*Doc
|
||||
template struct {
|
||||
home, index, article, doc *template.Template
|
||||
}
|
||||
atomFeed []byte // pre-rendered Atom feed
|
||||
@ -118,7 +119,8 @@ func NewServer(cfg Config) (*Server, error) {
|
||||
}
|
||||
|
||||
// Load content.
|
||||
err = s.loadDocs(filepath.Clean(cfg.ContentPath))
|
||||
content := filepath.Clean(cfg.ContentPath)
|
||||
err = s.loadDocs(content)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@ -191,6 +193,7 @@ func (s *Server) loadDocs(root string) error {
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if filepath.Ext(p) != ext {
|
||||
return nil
|
||||
}
|
||||
@ -227,12 +230,27 @@ func (s *Server) loadDocs(root string) error {
|
||||
// Pull out doc paths and tags and put in reverse-associating maps.
|
||||
s.docPaths = make(map[string]*Doc)
|
||||
s.docTags = make(map[string][]*Doc)
|
||||
s.redirects = make(map[string]string)
|
||||
for _, d := range s.docs {
|
||||
s.docPaths[strings.TrimPrefix(d.Path, s.cfg.BasePath)] = d
|
||||
for _, t := range d.Tags {
|
||||
s.docTags[t] = append(s.docTags[t], d)
|
||||
}
|
||||
}
|
||||
for _, d := range s.docs {
|
||||
for _, old := range d.OldURL {
|
||||
if !strings.HasPrefix(old, "/") {
|
||||
old = "/" + old
|
||||
}
|
||||
if _, ok := s.docPaths[old]; ok {
|
||||
return fmt.Errorf("redirect %s -> %s conflicts with document %s", old, d.Path, old)
|
||||
}
|
||||
if new, ok := s.redirects[old]; ok {
|
||||
return fmt.Errorf("redirect %s -> %s conflicts with redirect %s -> %s", old, d.Path, old, new)
|
||||
}
|
||||
s.redirects[old] = d.Path
|
||||
}
|
||||
}
|
||||
|
||||
// Pull out unique sorted list of tags.
|
||||
for t := range s.docTags {
|
||||
@ -425,6 +443,10 @@ func (s *Server) ServeHTTP(w http.ResponseWriter, r *http.Request) {
|
||||
w.Write(s.jsonFeed)
|
||||
return
|
||||
default:
|
||||
if redir, ok := s.redirects[p]; ok {
|
||||
http.Redirect(w, r, redir, http.StatusMovedPermanently)
|
||||
return
|
||||
}
|
||||
doc, ok := s.docPaths[p]
|
||||
if !ok {
|
||||
// Not a doc; try to just serve static content.
|
||||
|
@ -17,6 +17,7 @@ and other metadata, which looks like:
|
||||
15:04 2 Jan 2006
|
||||
Tags: foo, bar, baz
|
||||
Summary: This is a great document you want to read.
|
||||
OldURL: former-path-for-this-doc
|
||||
|
||||
The "# " prefix before the title indicates that this is
|
||||
a Markdown-enabled present file: it uses
|
||||
@ -33,8 +34,12 @@ the document.
|
||||
|
||||
The summary line gives a short summary used in blog feeds.
|
||||
|
||||
The old URL line, which may be repeated, gives an older (perhaps relative) URL
|
||||
for this document.
|
||||
A server might use these to generate appropriate redirects.
|
||||
|
||||
Only the title is required;
|
||||
the subtitle, date, tags, and summary lines are optional.
|
||||
the subtitle, date, tags, summary, and old URL lines are optional.
|
||||
In Markdown-enabled present, the summary defaults to being empty.
|
||||
In legacy present, the summary defaults to the first paragraph of text.
|
||||
|
||||
|
@ -79,6 +79,7 @@ type Doc struct {
|
||||
TitleNotes []string
|
||||
Sections []Section
|
||||
Tags []string
|
||||
OldURL []string
|
||||
}
|
||||
|
||||
// Author represents the person who wrote and/or is presenting the document.
|
||||
@ -546,6 +547,8 @@ func parseHeader(doc *Doc, isMarkdown bool, lines *Lines) error {
|
||||
doc.Tags = append(doc.Tags, tags...)
|
||||
} else if strings.HasPrefix(text, "Summary:") {
|
||||
doc.Summary = strings.TrimSpace(text[len("Summary:"):])
|
||||
} else if strings.HasPrefix(text, "OldURL:") {
|
||||
doc.OldURL = append(doc.OldURL, strings.TrimSpace(text[len("OldURL:"):]))
|
||||
} else if t, ok := parseTime(text); ok {
|
||||
doc.Time = t
|
||||
} else if doc.Subtitle == "" {
|
||||
|
Loading…
Reference in New Issue
Block a user