package plugins import ( "bytes" "fmt" "io" "text/template" "github.com/osteele/gojekyll/pages" ) type jekyllRedirectFromPlugin struct{ plugin } var redirectTemplate *template.Template func init() { register("jekyll-redirect-from", jekyllRedirectFromPlugin{}) tmpl, err := template.New("redirect_from").Parse(redirectFromTemplateSource) if err != nil { panic(err) } redirectTemplate = tmpl } func (p jekyllRedirectFromPlugin) PostRead(site Site) error { ps := site.Pages() newPages, err := p.processRedirectFrom(site, ps) if err != nil { return err } p.processRedirectTo(site, ps) for _, r := range newPages { site.AddDocument(r, true) } return nil } func (p jekyllRedirectFromPlugin) processRedirectFrom(site Site, ps []pages.Page) ([]pages.Document, error) { var ( cfg = site.Config() siteurl = cfg.AbsoluteURL baseurl = cfg.BaseURL prefix = siteurl + baseurl redirections = []pages.Document{} ) addRedirectFrom := func(from string, to pages.Page) { r := redirectionDoc{From: from, To: prefix + to.Permalink()} redirections = append(redirections, &r) } for _, p := range ps { sources, err := getStringArray(p, "redirect_from") if err != nil { return nil, err } for _, from := range sources { addRedirectFrom(from, p) } } return redirections, nil } func (p jekyllRedirectFromPlugin) processRedirectTo(site Site, ps []pages.Page) error { for _, p := range ps { sources, err := getStringArray(p, "redirect_to") if err != nil { return err } if len(sources) > 0 { r := redirectionDoc{From: p.Permalink(), To: sources[0]} p.SetContent(r.Content()) } } return nil } func getStringArray(p pages.Page, fieldName string) (out []string, err error) { if value, ok := p.FrontMatter()[fieldName]; ok { switch value := value.(type) { case []string: out = value case []interface{}: out = make([]string, len(value)) for i, item := range value { out[i] = fmt.Sprintf("%s", item) } case string: out = []string{value} default: err = fmt.Errorf("unimplemented redirect_from type %T", value) } } return } type redirectionDoc struct { From string To string } func (d *redirectionDoc) Permalink() string { return d.From } func (d *redirectionDoc) SourcePath() string { return "" } // FIXME bad design func (d *redirectionDoc) OutputExt() string { return ".html" } func (d *redirectionDoc) Published() bool { return true } func (d *redirectionDoc) Static() bool { return false } // FIXME means different things to different callers func (d *redirectionDoc) Categories() []string { return []string{} } func (d *redirectionDoc) Tags() []string { return []string{} } func (d *redirectionDoc) Content() []byte { buf := new(bytes.Buffer) if err := redirectTemplate.Execute(buf, d); err != nil { panic(err) } return buf.Bytes() } func (d *redirectionDoc) Write(w io.Writer) error { return redirectTemplate.Execute(w, d) } // Adapted from https://github.com/jekyll/jekyll-redirect-from const redirectFromTemplateSource = `