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: + + {{ 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: + + {{ 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"