diff --git a/embed/article/detail.html b/embed/article/detail.html
new file mode 100644
index 0000000..ece34bc
--- /dev/null
+++ b/embed/article/detail.html
@@ -0,0 +1,72 @@
+
+
+ {{.Title}}
+
+ #
+ Published:
+
+ {{.Post.Meta.FormattedDate}}
+
+ {{ if .Post.User.Config.AuthorName }}
+ by
+
+ {{ if .Post.User.AvatarUrl }}
+
+ {{ end }}
+ {{.Post.User.Config.AuthorName}}
+
+ {{ end }}
+
+
+
+
+
+ {{ if .Post.Meta.Reply.Url }}
+
+ In reply to:
+ {{ if .Post.Meta.Reply.Text }}
+ {{.Post.Meta.Reply.Text}}
+ {{ else }}
+ {{.Post.Meta.Reply.Url}}
+ {{ end }}
+
+
+ {{ end }}
+
+ {{ if .Post.Meta.Bookmark.Url }}
+
+ Bookmark:
+ {{ if .Post.Meta.Bookmark.Text }}
+ {{.Post.Meta.Bookmark.Text}}
+ {{ else }}
+ {{.Post.Meta.Bookmark.Url}}
+ {{ end }}
+
+
+ {{ end }}
+
+
+ {{.Content}}
+
+
+
+ {{if .Post.ApprovedIncomingWebmentions}}
+
+ Webmentions
+
+
+ {{end}}
+
\ No newline at end of file
diff --git a/embed/note/detail.html b/embed/note/detail.html
new file mode 100644
index 0000000..ece34bc
--- /dev/null
+++ b/embed/note/detail.html
@@ -0,0 +1,72 @@
+
+
+ {{.Title}}
+
+ #
+ Published:
+
+ {{.Post.Meta.FormattedDate}}
+
+ {{ if .Post.User.Config.AuthorName }}
+ by
+
+ {{ if .Post.User.AvatarUrl }}
+
+ {{ end }}
+ {{.Post.User.Config.AuthorName}}
+
+ {{ end }}
+
+
+
+
+
+ {{ if .Post.Meta.Reply.Url }}
+
+ In reply to:
+ {{ if .Post.Meta.Reply.Text }}
+ {{.Post.Meta.Reply.Text}}
+ {{ else }}
+ {{.Post.Meta.Reply.Url}}
+ {{ end }}
+
+
+ {{ end }}
+
+ {{ if .Post.Meta.Bookmark.Url }}
+
+ Bookmark:
+ {{ if .Post.Meta.Bookmark.Text }}
+ {{.Post.Meta.Bookmark.Text}}
+ {{ else }}
+ {{.Post.Meta.Bookmark.Url}}
+ {{ end }}
+
+
+ {{ end }}
+
+
+ {{.Content}}
+
+
+
+ {{if .Post.ApprovedIncomingWebmentions}}
+
+ Webmentions
+
+
+ {{end}}
+
\ No newline at end of file
diff --git a/embed/page/detail.html b/embed/page/detail.html
new file mode 100644
index 0000000..c2f94b7
--- /dev/null
+++ b/embed/page/detail.html
@@ -0,0 +1,34 @@
+
+
+ {{.Title}}
+
+ #
+
+
+
+
+
+
+ {{.Content}}
+
+
+
+ {{if .Post.ApprovedIncomingWebmentions}}
+
+ Webmentions
+
+
+ {{end}}
+
\ No newline at end of file
diff --git a/post.go b/post.go
index 6b8cb04..03adbed 100644
--- a/post.go
+++ b/post.go
@@ -25,6 +25,40 @@ type Post struct {
wmLock sync.Mutex
}
+func (post *Post) TemplateDir() string {
+ return "article"
+}
+
+type IPost interface {
+ TemplateDir() string
+
+ Id() string
+ User() *User
+ Dir() string
+ IncomingWebmentionsFile() string
+ OutgoingWebmentionsFile() string
+ MediaDir() string
+ UrlPath() string
+ FullUrl() string
+ UrlMediaPath(filename string) string
+ Title() string
+ ContentFile() string
+ Meta() PostMeta
+ Content() []byte
+ RenderedContent() string
+ Aliases() []string
+ LoadMeta() error
+ IncomingWebmentions() []WebmentionIn
+ OutgoingWebmentions() []WebmentionOut
+ PersistIncomingWebmention(webmention WebmentionIn) error
+ PersistOutgoingWebmention(webmention *WebmentionOut) error
+ AddIncomingWebmention(source string) error
+ EnrichWebmention(webmention WebmentionIn) error
+ ApprovedIncomingWebmentions() []WebmentionIn
+ ScanForLinks() error
+ SendWebmention(webmention WebmentionOut) error
+}
+
type Reply struct {
Url string `yaml:"url"`
Text string `yaml:"text"`
diff --git a/post_types.go b/post_types.go
new file mode 100644
index 0000000..2f0cdeb
--- /dev/null
+++ b/post_types.go
@@ -0,0 +1,25 @@
+package owl
+
+type Note struct {
+ Post
+}
+
+func (n *Note) TemplateDir() string {
+ return "note"
+}
+
+type Article struct {
+ Post
+}
+
+func (a *Article) TemplateDir() string {
+ return "article"
+}
+
+type Page struct {
+ Post
+}
+
+func (p *Page) TemplateDir() string {
+ return "page"
+}
diff --git a/renderer.go b/renderer.go
index b2f7d85..754526c 100644
--- a/renderer.go
+++ b/renderer.go
@@ -3,6 +3,7 @@ package owl
import (
"bytes"
_ "embed"
+ "fmt"
"html/template"
"strings"
)
@@ -17,7 +18,7 @@ type PageContent struct {
type PostRenderData struct {
Title string
- Post *Post
+ Post IPost
Content template.HTML
}
@@ -118,23 +119,26 @@ func renderIntoBaseTemplate(user User, data PageContent) (string, error) {
return html.String(), err
}
-func renderPostContent(post *Post) (string, error) {
+func renderPostContent(post IPost) (string, error) {
buf := post.RenderedContent()
- postHtml, err := renderEmbedTemplate("embed/post.html", PostRenderData{
- Title: post.Title(),
- Post: post,
- Content: template.HTML(buf),
- })
+ postHtml, err := renderEmbedTemplate(
+ fmt.Sprintf("embed/%s/detail.html", post.TemplateDir()),
+ PostRenderData{
+ Title: post.Title(),
+ Post: post,
+ Content: template.HTML(buf),
+ },
+ )
return postHtml, err
}
-func RenderPost(post *Post) (string, error) {
+func RenderPost(post IPost) (string, error) {
postHtml, err := renderPostContent(post)
if err != nil {
return "", err
}
- return renderIntoBaseTemplate(*post.user, PageContent{
+ return renderIntoBaseTemplate(*post.User(), PageContent{
Title: post.Title(),
Description: post.Meta().Description,
Content: template.HTML(postHtml),
diff --git a/repository.go b/repository.go
index 1c61c89..923d7c6 100644
--- a/repository.go
+++ b/repository.go
@@ -158,12 +158,12 @@ func (repo Repository) GetUser(name string) (User, error) {
return user, nil
}
-func (repo Repository) PostAliases() (map[string]*Post, error) {
+func (repo Repository) PostAliases() (map[string]IPost, error) {
users, err := repo.Users()
if err != nil {
return nil, err
}
- aliases := make(map[string]*Post)
+ aliases := make(map[string]IPost)
for _, user := range users {
user_aliases, err := user.PostAliases()
if err != nil {
diff --git a/repository_test.go b/repository_test.go
index 95eb9a8..3d5b3ae 100644
--- a/repository_test.go
+++ b/repository_test.go
@@ -213,7 +213,7 @@ func TestCanGetMapWithAllPostAliases(t *testing.T) {
posts, _ := user.PublishedPosts()
assertions.AssertLen(t, posts, 1)
- var aliases map[string]*owl.Post
+ var aliases map[string]owl.IPost
aliases, err := repo.PostAliases()
assertions.AssertNoError(t, err, "Error getting post aliases: ")
assertions.AssertMapLen(t, aliases, 2)
@@ -247,7 +247,7 @@ func TestAliasesHaveCorrectPost(t *testing.T) {
posts, _ := user.PublishedPosts()
assertions.AssertLen(t, posts, 2)
- var aliases map[string]*owl.Post
+ var aliases map[string]owl.IPost
aliases, err := repo.PostAliases()
assertions.AssertNoError(t, err, "Error getting post aliases: ")
assertions.AssertMapLen(t, aliases, 2)
diff --git a/user.go b/user.go
index d7ac96e..e264ebb 100644
--- a/user.go
+++ b/user.go
@@ -197,9 +197,9 @@ func (user User) FaviconUrl() string {
return ""
}
-func (user User) AllPosts() ([]*Post, error) {
+func (user User) AllPosts() ([]IPost, error) {
postFiles := listDir(path.Join(user.Dir(), "public"))
- posts := make([]*Post, 0)
+ posts := make([]IPost, 0)
for _, id := range postFiles {
// if is a directory and has index.md, add to posts
if dirExists(path.Join(user.Dir(), "public", id)) {
@@ -211,7 +211,7 @@ func (user User) AllPosts() ([]*Post, error) {
}
type PostWithDate struct {
- post *Post
+ post IPost
date time.Time
}
@@ -233,7 +233,7 @@ func (user User) AllPosts() ([]*Post, error) {
return posts, nil
}
-func (user User) PublishedPosts() ([]*Post, error) {
+func (user User) PublishedPosts() ([]IPost, error) {
posts, _ := user.AllPosts()
// remove drafts
@@ -249,7 +249,7 @@ func (user User) PublishedPosts() ([]*Post, error) {
return posts, nil
}
-func (user User) PrimaryFeedPosts() ([]*Post, error) {
+func (user User) PrimaryFeedPosts() ([]IPost, error) {
config := user.Config()
include := config.PrimaryListInclude
if len(include) == 0 {
@@ -262,7 +262,7 @@ func (user User) PrimaryFeedPosts() ([]*Post, error) {
})
}
-func (user User) GetPostsOfList(list PostList) ([]*Post, error) {
+func (user User) GetPostsOfList(list PostList) ([]IPost, error) {
posts, _ := user.PublishedPosts()
// remove posts not included
@@ -278,17 +278,26 @@ func (user User) GetPostsOfList(list PostList) ([]*Post, error) {
return posts, nil
}
-func (user User) GetPost(id string) (*Post, error) {
+func (user User) GetPost(id string) (IPost, error) {
// check if posts index.md exists
if !fileExists(path.Join(user.Dir(), "public", id, "index.md")) {
return &Post{}, fmt.Errorf("post %s does not exist", id)
}
post := Post{user: &user, id: id}
+ if post.Meta().Type == "" {
+ return &Article{Post: post}, nil
+ }
+ switch post.Meta().Type {
+ case "article":
+ return &Article{Post: post}, nil
+ case "note":
+ return &Note{Post: post}, nil
+ }
return &post, nil
}
-func (user User) CreateNewPostFull(meta PostMeta, content string) (*Post, error) {
+func (user User) CreateNewPostFull(meta PostMeta, content string) (IPost, error) {
slugHint := meta.Title
if slugHint == "" {
slugHint = "note"
@@ -326,10 +335,10 @@ func (user User) CreateNewPostFull(meta PostMeta, content string) (*Post, error)
os.WriteFile(post.ContentFile(), []byte(initial_content), 0644)
// create media dir
os.Mkdir(post.MediaDir(), 0755)
- return &post, nil
+ return user.GetPost(post.Id())
}
-func (user User) CreateNewPost(title string, draft bool) (*Post, error) {
+func (user User) CreateNewPost(title string, draft bool) (IPost, error) {
meta := PostMeta{
Title: title,
Date: time.Now(),
@@ -359,8 +368,8 @@ func (user User) SetConfig(new_config UserConfig) error {
return saveToYaml(user.ConfigFile(), new_config)
}
-func (user User) PostAliases() (map[string]*Post, error) {
- post_aliases := make(map[string]*Post)
+func (user User) PostAliases() (map[string]IPost, error) {
+ post_aliases := make(map[string]IPost)
posts, err := user.PublishedPosts()
if err != nil {
return post_aliases, err
diff --git a/user_test.go b/user_test.go
index 89f07b7..9fabe4d 100644
--- a/user_test.go
+++ b/user_test.go
@@ -225,7 +225,7 @@ func TestPostsSortedByPublishingDateLatestFirst(t *testing.T) {
func TestPostsSortedByPublishingDateLatestFirst2(t *testing.T) {
user := getTestUser()
// Create a new post
- posts := []*owl.Post{}
+ posts := []owl.IPost{}
for i := 59; i >= 0; i-- {
post, _ := user.CreateNewPost("testpost", false)
content := "---\n"