refactoring reading Meta and RenderedContent

This commit is contained in:
Niko Abeler 2022-08-22 21:15:36 +02:00
parent e5f7417618
commit 4236541441
7 changed files with 94 additions and 23 deletions

View File

@ -95,7 +95,7 @@ func postHandler(repo *owl.Repository) func(http.ResponseWriter, *http.Request,
return return
} }
_, meta := post.MarkdownData() meta := post.Meta()
if meta.Draft { if meta.Draft {
println("Post is a draft") println("Post is a draft")
notFoundHandler(repo)(w, r) notFoundHandler(repo)(w, r)

47
post.go
View File

@ -16,6 +16,8 @@ type Post struct {
user *User user *User
id string id string
title string title string
metaLoaded bool
meta PostMeta
} }
type PostMeta struct { type PostMeta struct {
@ -57,17 +59,24 @@ func (post Post) ContentFile() string {
return path.Join(post.Dir(), "index.md") return path.Join(post.Dir(), "index.md")
} }
func (post *Post) Meta() PostMeta {
if !post.metaLoaded {
post.LoadMeta()
}
return post.meta
}
func (post Post) Content() []byte { func (post Post) Content() []byte {
// read file // read file
data, _ := ioutil.ReadFile(post.ContentFile()) data, _ := ioutil.ReadFile(post.ContentFile())
return data return data
} }
func (post Post) MarkdownData() (bytes.Buffer, PostMeta) { func (post Post) RenderedContent() bytes.Buffer {
data := post.Content() data := post.Content()
// get yaml metadata block // trim yaml block
meta := PostMeta{} // TODO this can be done nicer
trimmedData := bytes.TrimSpace(data) trimmedData := bytes.TrimSpace(data)
// check first line is --- // check first line is ---
if string(trimmedData[0:4]) == "---\n" { if string(trimmedData[0:4]) == "---\n" {
@ -75,8 +84,6 @@ func (post Post) MarkdownData() (bytes.Buffer, PostMeta) {
// find --- end // find --- end
end := bytes.Index(trimmedData, []byte("\n---\n")) end := bytes.Index(trimmedData, []byte("\n---\n"))
if end != -1 { if end != -1 {
metaData := trimmedData[:end]
yaml.Unmarshal(metaData, &meta)
data = trimmedData[end+5:] data = trimmedData[end+5:]
} }
} }
@ -100,13 +107,35 @@ func (post Post) MarkdownData() (bytes.Buffer, PostMeta) {
if err := markdown.Convert(data, &buf, parser.WithContext(context)); err != nil { if err := markdown.Convert(data, &buf, parser.WithContext(context)); err != nil {
panic(err) panic(err)
} }
// metaData := meta.Get(context)
return buf, meta return buf
} }
func (post Post) Aliases() []string { func (post Post) Aliases() []string {
_, metaData := post.MarkdownData() return post.Meta().Aliases
return metaData.Aliases }
func (post *Post) LoadMeta() error {
data := post.Content()
// get yaml metadata block
meta := PostMeta{}
trimmedData := bytes.TrimSpace(data)
// check first line is ---
if string(trimmedData[0:4]) == "---\n" {
trimmedData = trimmedData[4:]
// find --- end
end := bytes.Index(trimmedData, []byte("\n---\n"))
if end != -1 {
metaData := trimmedData[:end]
err := yaml.Unmarshal(metaData, &meta)
if err != nil {
return err
}
}
}
post.meta = meta
return nil
} }

View File

@ -79,7 +79,7 @@ func TestDraftInMetaData(t *testing.T) {
content += "\n" content += "\n"
content += "Write your post here.\n" content += "Write your post here.\n"
os.WriteFile(post.ContentFile(), []byte(content), 0644) os.WriteFile(post.ContentFile(), []byte(content), 0644)
_, meta := post.MarkdownData() meta := post.Meta()
if !meta.Draft { if !meta.Draft {
t.Error("Draft should be true") t.Error("Draft should be true")
} }
@ -97,7 +97,7 @@ func TestNoRawHTMLIfDisallowedByRepo(t *testing.T) {
content += "\n" content += "\n"
content += "<script>alert('foo')</script>\n" content += "<script>alert('foo')</script>\n"
os.WriteFile(post.ContentFile(), []byte(content), 0644) os.WriteFile(post.ContentFile(), []byte(content), 0644)
html, _ := post.MarkdownData() html := post.RenderedContent()
html_str := html.String() html_str := html.String()
if strings.Contains(html_str, "<script>") { if strings.Contains(html_str, "<script>") {
t.Error("HTML should not be allowed") t.Error("HTML should not be allowed")
@ -116,9 +116,50 @@ func TestRawHTMLIfAllowedByRepo(t *testing.T) {
content += "\n" content += "\n"
content += "<script>alert('foo')</script>\n" content += "<script>alert('foo')</script>\n"
os.WriteFile(post.ContentFile(), []byte(content), 0644) os.WriteFile(post.ContentFile(), []byte(content), 0644)
html, _ := post.MarkdownData() html := post.RenderedContent()
html_str := html.String() html_str := html.String()
if !strings.Contains(html_str, "<script>") { if !strings.Contains(html_str, "<script>") {
t.Error("HTML should be allowed") t.Error("HTML should be allowed")
} }
} }
func TestLoadMeta(t *testing.T) {
repo := getTestRepo()
repo.SetAllowRawHtml(true)
user, _ := repo.CreateUser("testuser")
post, _ := user.CreateNewPost("testpost")
content := "---\n"
content += "title: test\n"
content += "draft: true\n"
content += "date: Wed, 17 Aug 2022 10:50:02 +0000\n"
content += "aliases:\n"
content += " - foo/bar/\n"
content += "---\n"
content += "\n"
content += "<script>alert('foo')</script>\n"
os.WriteFile(post.ContentFile(), []byte(content), 0644)
err := post.LoadMeta()
if err != nil {
t.Errorf("Got Error: %v", err)
}
if post.Meta().Title != "test" {
t.Errorf("Expected title: %s, got %s", "test", post.Meta().Title)
}
if len(post.Meta().Aliases) != 1 || post.Meta().Aliases[0] != "foo/bar/" {
t.Errorf("Expected title: %v, got %v", []string{"foo/bar/"}, post.Meta().Aliases)
}
if post.Meta().Date != "Wed, 17 Aug 2022 10:50:02 +0000" {
t.Errorf("Expected title: %s, got %s", "Wed, 17 Aug 2022 10:50:02 +0000", post.Meta().Title)
}
if post.Meta().Draft != true {
t.Errorf("Expected title: %v, got %v", true, post.Meta().Draft)
}
}

View File

@ -68,7 +68,7 @@ func renderIntoBaseTemplate(user User, data PageContent) (string, error) {
} }
func RenderPost(post Post) (string, error) { func RenderPost(post Post) (string, error) {
buf, _ := post.MarkdownData() buf := post.RenderedContent()
postHtml, err := renderEmbedTemplate("embed/post.html", PostRenderData{ postHtml, err := renderEmbedTemplate("embed/post.html", PostRenderData{
Title: post.Title(), Title: post.Title(),
Post: template.HTML(buf.String()), Post: template.HTML(buf.String()),

2
rss.go
View File

@ -41,7 +41,7 @@ func RenderRSSFeed(user User) (string, error) {
posts, _ := user.Posts() posts, _ := user.Posts()
for _, post := range posts { for _, post := range posts {
_, meta := post.MarkdownData() meta := post.Meta()
rss.Channel.Items = append(rss.Channel.Items, RSSItem{ rss.Channel.Items = append(rss.Channel.Items, RSSItem{
Guid: post.FullUrl(), Guid: post.FullUrl(),
Title: post.Title(), Title: post.Title(),

View File

@ -68,7 +68,7 @@ func (user User) Posts() ([]*Post, error) {
// remove drafts // remove drafts
n := 0 n := 0
for _, post := range posts { for _, post := range posts {
_, meta := post.MarkdownData() meta := post.Meta()
if !meta.Draft { if !meta.Draft {
posts[n] = post posts[n] = post
n++ n++
@ -83,7 +83,7 @@ func (user User) Posts() ([]*Post, error) {
postDates := make([]PostWithDate, len(posts)) postDates := make([]PostWithDate, len(posts))
for i, post := range posts { for i, post := range posts {
_, meta := post.MarkdownData() meta := post.Meta()
date, err := time.Parse(time.RFC1123Z, meta.Date) date, err := time.Parse(time.RFC1123Z, meta.Date)
if err != nil { if err != nil {
// invalid date -> use 1970-01-01 // invalid date -> use 1970-01-01
@ -111,8 +111,9 @@ func (user User) GetPost(id string) (Post, error) {
} }
post := Post{user: &user, id: id} post := Post{user: &user, id: id}
_, metaData := post.MarkdownData() // post.loadMeta()
title := metaData.Title meta := post.Meta()
title := meta.Title
post.title = fmt.Sprint(title) post.title = fmt.Sprint(title)
return post, nil return post, nil

View File

@ -41,7 +41,7 @@ func TestCreateNewPostAddsDateToMetaBlock(t *testing.T) {
user.CreateNewPost("testpost") user.CreateNewPost("testpost")
posts, _ := user.Posts() posts, _ := user.Posts()
post, _ := user.GetPost(posts[0].Id()) post, _ := user.GetPost(posts[0].Id())
_, meta := post.MarkdownData() meta := post.Meta()
if meta.Date == "" { if meta.Date == "" {
t.Error("Found no date. Got: " + meta.Date) t.Error("Found no date. Got: " + meta.Date)
} }