// ReadPosts read posts files in srcDir/post func ReadPosts(ctx *Context) ([]*model.Post, error) { srcDir := ctx.SrcPostDir() if !com.IsDir(srcDir) { return nil, fmt.Errorf("posts directory '%s' is missing", srcDir) } log15.Info("Read|Posts|%s", srcDir) // try load post.toml or post.ini to read total meta file var ( err error postMeta = make(map[string]*model.Post) ) for t, f := range model.ShouldPostMetaFiles() { file := filepath.Join(ctx.SrcDir(), f) if !com.IsFile(file) { continue } postMeta, err = model.NewPostsFrontMatter(file, t) if err != nil { return nil, err } log15.Debug("Read|PostMeta|%s", file) break } var posts []*model.Post err = filepath.Walk(srcDir, func(p string, fi os.FileInfo, err error) error { if err != nil { return err } if fi.IsDir() { return nil } p = filepath.ToSlash(p) if filepath.Ext(p) == ".md" { metaKey := strings.TrimPrefix(p, filepath.ToSlash(srcDir+"/")) log15.Debug("Read|%s|%v", p, postMeta[metaKey] != nil) post, err := model.NewPostOfMarkdown(p, postMeta[metaKey]) if err != nil { log15.Warn("Read|Post|%s|%v", p, err) return nil } else if post != nil && !post.Draft { posts = append(posts, post) } if post.Draft == true { log15.Warn("Draft|%s", p) } } return nil }) sort.Sort(model.Posts(posts)) return posts, err }
// AssembleSource assemble some extra data in Source, // such as page nodes, i18n status. // it need be used after posts and pages are loaded func AssembleSource(ctx *Context) { if ctx.Source == nil || ctx.Theme == nil { ctx.Err = fmt.Errorf("need sources data and theme to assemble") return } ctx.Source.Nav.SetPrefix(ctx.Source.Meta.Path) ctx.Source.Tags = make(map[string]*model.Tag) ctx.Source.TagPosts = make(map[string]*model.TagPosts) ctx.Source.PagePosts = make(map[int]*model.PagerPosts) r, hr := newReplacer(ctx.Source.Meta.Path), newReplacerInHTML(ctx.Source.Meta.Path) ctx.Source.Meta.Cover = r.Replace(ctx.Source.Meta.Cover) for _, a := range ctx.Source.Authors { a.Avatar = r.Replace(a.Avatar) } // fill post data for _, p := range ctx.Source.Posts { if ctx.Source.Meta.Path != "" && ctx.Source.Meta.Path != "/" { p.SetURL(path.Join(ctx.Source.Meta.Path, p.URL())) } p.SetDestURL(filepath.Join(ctx.DstDir(), p.URL())) p.SetPlaceholder(r, hr) ctx.Tree.Add(p.DestURL(), p.Title, model.TreePost, 0) if p.Author == nil { p.Author = ctx.Source.Authors[p.AuthorName] } for _, t := range p.Tags { ctx.Source.Tags[t.Name] = t if ctx.Source.TagPosts[t.Name] == nil { ctx.Source.TagPosts[t.Name] = &model.TagPosts{ Posts: []*model.Post{p}, Tag: t, } } else { ctx.Source.TagPosts[t.Name].Posts = append(ctx.Source.TagPosts[t.Name].Posts, p) } } } // fill page data for _, p := range ctx.Source.Pages { if ctx.Source.Meta.Path != "" && ctx.Source.Meta.Path != "/" { p.SetURL(path.Join(ctx.Source.Meta.Path, p.URL())) } p.SetDestURL(filepath.Join(ctx.DstDir(), p.URL())) p.SetPlaceholder(hr) treeType := model.TreePage if p.Node { treeType = model.TreePageNode } ctx.Tree.Add(p.DestURL(), p.Title, treeType, p.Sort) if p.Author == nil { p.Author = ctx.Source.Authors[p.AuthorName] } } // prepare tag posts for _, tp := range ctx.Source.TagPosts { sort.Sort(model.Posts(tp.Posts)) tp.SetDestURL(path.Join(ctx.DstDir(), ctx.Source.Meta.Path, tp.Tag.URL)) ctx.Tree.Add(tp.DestURL(), "", model.TreePostTag, 0) } // prepare archives archives := model.NewArchive(ctx.Source.Posts) archives.SetDestURL(filepath.Join(ctx.DstDir(), archives.DestURL())) ctx.Source.Archive = archives ctx.Tree.Add(archives.DestURL(), "Archive", model.TreeArchive, 0) // prepare paged posts var ( cursor = helper.NewPagerCursor(4, len(ctx.Source.Posts)) page = 1 layout = "posts/%d" ) for { pager := cursor.Page(page) if pager == nil { ctx.Source.PostPage = page - 1 break } currentPosts := ctx.Source.Posts[pager.Begin:pager.End] pager.SetLayout(path.Join(ctx.Source.Meta.Path, "/"+layout+".html")) pageURL := path.Join(ctx.Source.Meta.Path, fmt.Sprintf(layout+".html", pager.Current)) pp := &model.PagerPosts{ Posts: currentPosts, Pager: pager, URL: pageURL, } pp.SetDestURL(path.Join(ctx.DstDir(), pageURL)) ctx.Source.PagePosts[pager.Current] = pp ctx.Tree.Add(pp.DestURL(), "", model.TreePostList, 0) if pager.Current == 1 { // use new object, not pp pp2 := model.PagerPosts{ Posts: currentPosts, Pager: pager, } pp2.SetDestURL(path.Join(ctx.DstDir(), "index.html")) ctx.Source.IndexPosts = pp2 ctx.Tree.Add(path.Join(ctx.DstDir(), "index.html"), "Home", model.TreeIndex, 0) } page++ } ctx.Tree.Add(path.Join(ctx.DstDir(), ctx.Source.Meta.Path, "feed.xml"), "Feed", model.TreeXML, 0) ctx.Tree.Add(path.Join(ctx.DstDir(), ctx.Source.Meta.Path, "sitemap.xml"), "Sitemap", model.TreeXML, 0) if ctx.Err = ctx.Theme.Load(); ctx.Err != nil { return } log15.Info("Assemble|Done") }