diff --git a/assets/css/main.scss b/assets/css/main.scss index c8f0344..dc6ad7d 100644 --- a/assets/css/main.scss +++ b/assets/css/main.scss @@ -10,21 +10,7 @@ $container-max-widths: ( @import "bootstrap/scss/bootstrap.scss"; -// Local classes - -.post-form { - display: grid; - grid-template-rows: min-content auto min-content; - position: absolute; - top: 0; - bottom: 0; - left: 0; - right: 0; -} - -.post-form textarea { - height: 100%; -} +// Post list .postlist .post img { max-width: 300px; @@ -32,6 +18,49 @@ $container-max-widths: ( max-height: 300px; } +.postlist .post-date { + font-size: 0.9rem; +} + +// Post form + +// Post edit page styling +.post-edit-page { + height: 100vh; +} + +.post-edit-page main { + display: flex; + flex-direction: column; + overflow: hidden; +} + +.post-edit-page .post-form { + flex: 1; + display: flex; + flex-direction: column; + min-height: 0; +} + +.post-edit-page .post-form .row { + flex: 1; + display: flex; + min-height: 0; +} + +.post-edit-page .post-form .col-md-9 { + display: flex; + flex-direction: column; +} + +.post-edit-page .post-form textarea { + flex: 1; + resize: vertical; + min-height: 300px; +} + + + .show-upload figure img { max-width: 100vw; height: auto; diff --git a/handlers/posts.go b/handlers/posts.go index a339685..a133758 100644 --- a/handlers/posts.go +++ b/handlers/posts.go @@ -53,6 +53,7 @@ func (ph PostsHandler) New(c fiber.Ctx) error { "post": p, "categories": cats, "selectedCategories": map[int64]bool{}, + "bodyClass": "post-edit-page", }) } @@ -93,6 +94,7 @@ func (ph PostsHandler) Edit(c fiber.Ctx) error { "post": post, "categories": cats, "selectedCategories": selectedCategories, + "bodyClass": "post-edit-page", }) })) } diff --git a/layouts/simplecss/categories_list.html b/layouts/simplecss/categories_list.html deleted file mode 100644 index 32331f6..0000000 --- a/layouts/simplecss/categories_list.html +++ /dev/null @@ -1,9 +0,0 @@ -

Categories

- \ No newline at end of file diff --git a/layouts/simplecss/categories_single.html b/layouts/simplecss/categories_single.html deleted file mode 100644 index e8d59d1..0000000 --- a/layouts/simplecss/categories_single.html +++ /dev/null @@ -1,16 +0,0 @@ -

{{ .Category.Name }}

-{{ if .DescriptionHTML }} -
{{ .DescriptionHTML }}
-{{ end }} -{{ range .Posts }} - {{ if .Post.Title }}

{{ .Post.Title }}

{{ end }} - {{ .HTML }} - {{ format_date .Post.PublishedAt }} - {{ if .Categories }} -

- {{ range .Categories }} - {{ .Name }} - {{ end }} -

- {{ end }} -{{ end }} \ No newline at end of file diff --git a/layouts/simplecss/fs.go b/layouts/simplecss/fs.go index 2c1b2fb..d82f6ae 100644 --- a/layouts/simplecss/fs.go +++ b/layouts/simplecss/fs.go @@ -2,5 +2,6 @@ package simplecss import "embed" -//go:embed *.html +//go:embed templates/*.html +//go:embed static/* var FS embed.FS diff --git a/layouts/simplecss/posts_list.html b/layouts/simplecss/posts_list.html deleted file mode 100644 index e6a77fe..0000000 --- a/layouts/simplecss/posts_list.html +++ /dev/null @@ -1,12 +0,0 @@ -{{ range .Posts }} - {{ if .Post.Title }}

{{ .Post.Title }}

{{ end }} - {{ .HTML }} - {{ format_date .Post.PublishedAt }} - {{ if .Categories }} -

- {{ range .Categories }} - {{ .Name }} - {{ end }} -

- {{ end }} -{{ end }} \ No newline at end of file diff --git a/layouts/simplecss/posts_single.html b/layouts/simplecss/posts_single.html deleted file mode 100644 index cda9bb2..0000000 --- a/layouts/simplecss/posts_single.html +++ /dev/null @@ -1,10 +0,0 @@ -{{ if .Post.Title }}

{{ .Post.Title }}

{{ end }} -{{ .HTML }} -{{ format_date .Post.PublishedAt }} -{{ if .Categories }} -

- {{ range .Categories }} - {{ .Name }} - {{ end }} -

-{{ end }} \ No newline at end of file diff --git a/layouts/simplecss/static/style.css b/layouts/simplecss/static/style.css new file mode 100644 index 0000000..cdfc4c2 --- /dev/null +++ b/layouts/simplecss/static/style.css @@ -0,0 +1,55 @@ +.h-entry { + margin-block-start: 1.5rem; + margin-block-end: 2.5rem; +} + +.post-meta { + display: flex; + flex-direction: row; + justify-content: space-between; + font-size: 0.95rem; +} + +.post-meta a { + color: var(--text-light); + text-decoration: none; +} + +.post-meta a:hover { + text-decoration: underline; +} + +.post-categories { + display: inline-flex; + gap: 0.5rem; +} + +.post-categories a:before { + content: "#"; +} + +/* Category list */ + +ul.category-list { + list-style: none; + padding-inline-start: 0; +} + +ul.category-list li { + display: flex; + flex-direction: row; + + justify-content: start; + gap: 4rem; +} + +ul.category-list span.category-list-name { + min-width: 15vw; +} + +/* Category single */ + +.category-description { + margin-block-start: 1.5rem; + margin-block-end: 2.5rem; +} \ No newline at end of file diff --git a/layouts/simplecss/templates/_post_meta.html b/layouts/simplecss/templates/_post_meta.html new file mode 100644 index 0000000..a042f41 --- /dev/null +++ b/layouts/simplecss/templates/_post_meta.html @@ -0,0 +1,10 @@ +
+ {{ format_date .Post.PublishedAt }} + {{ if .Categories }} +
+ {{ range .Categories }} + {{ .Name }} + {{ end }} +
+ {{ end }} +
\ No newline at end of file diff --git a/layouts/simplecss/templates/categories_list.html b/layouts/simplecss/templates/categories_list.html new file mode 100644 index 0000000..e5fc8c8 --- /dev/null +++ b/layouts/simplecss/templates/categories_list.html @@ -0,0 +1,9 @@ +

Categories

+ \ No newline at end of file diff --git a/layouts/simplecss/templates/categories_single.html b/layouts/simplecss/templates/categories_single.html new file mode 100644 index 0000000..deaeb02 --- /dev/null +++ b/layouts/simplecss/templates/categories_single.html @@ -0,0 +1,11 @@ +

{{ .Category.Name }}

+{{ if .DescriptionHTML }} +
{{ .DescriptionHTML }}
+{{ end }} +{{ range .Posts }} +
+ {{ if .Post.Title }}

{{ .Post.Title }}

{{ end }} + {{ .HTML }} + {{ template "_post_meta.html" . }} +
+{{ end }} \ No newline at end of file diff --git a/layouts/simplecss/layout_main.html b/layouts/simplecss/templates/layout_main.html similarity index 89% rename from layouts/simplecss/layout_main.html rename to layouts/simplecss/templates/layout_main.html index cc2e616..4aa5199 100644 --- a/layouts/simplecss/layout_main.html +++ b/layouts/simplecss/templates/layout_main.html @@ -7,6 +7,7 @@ +
diff --git a/layouts/simplecss/templates/posts_list.html b/layouts/simplecss/templates/posts_list.html new file mode 100644 index 0000000..5f10f1e --- /dev/null +++ b/layouts/simplecss/templates/posts_list.html @@ -0,0 +1,8 @@ +{{ range .Posts }} +
+ {{ if .Post.Title }}

{{ .Post.Title }}

{{ end }} + {{ .HTML }} + + {{ template "_post_meta.html" . }} +
+{{ end }} \ No newline at end of file diff --git a/layouts/simplecss/templates/posts_single.html b/layouts/simplecss/templates/posts_single.html new file mode 100644 index 0000000..8895b19 --- /dev/null +++ b/layouts/simplecss/templates/posts_single.html @@ -0,0 +1,5 @@ +
+ {{ if .Post.Title }}

{{ .Post.Title }}

{{ end }} + {{ .HTML }} + {{ template "_post_meta.html" . }} +
\ No newline at end of file diff --git a/providers/sitebuilder/builder.go b/providers/sitebuilder/builder.go index 5775149..1a4275d 100644 --- a/providers/sitebuilder/builder.go +++ b/providers/sitebuilder/builder.go @@ -6,7 +6,9 @@ import ( "fmt" "html/template" "io" + "io/fs" "iter" + "log" "os" "path/filepath" "strings" @@ -31,11 +33,15 @@ type Builder struct { func New(site pubmodel.Site, opts Options) (*Builder, error) { tmpls, err := template.New(""). Funcs(templateFns(site, opts)). - ParseFS(opts.TemplatesFS, tmplNamePostSingle, tmplNamePostList, tmplNameLayoutMain, tmplNameCategoryList, tmplNameCategorySingle) + ParseFS(opts.TemplatesFS, "*.html") if err != nil { return nil, err } + for _, t := range tmpls.Templates() { + log.Printf("Loaded template %s", t.Name()) + } + return &Builder{ site: site, opts: opts, @@ -109,6 +115,9 @@ func (b *Builder) BuildSite(outDir string) error { return b.writeUploads(buildCtx, b.site.Uploads) }) + // Build static assets + eg.Go(func() error { return b.writeStaticAssets(buildCtx) }) + return eg.Wait() } @@ -176,10 +185,11 @@ func (b *Builder) renderFeeds(ctx buildContext, postIter iter.Seq[models.Maybe[* } feed.Items = append(feed.Items, &feedhub.Item{ - Id: filepath.Join(b.site.BaseURL, post.GUID), - Title: postTitle, - Link: &feedhub.Link{Href: renderedPost.PostURL}, - Content: string(renderedPost.HTML), + Id: filepath.Join(b.site.BaseURL, post.GUID), + Title: postTitle, + Link: &feedhub.Link{Href: renderedPost.PostURL}, + Content: string(renderedPost.HTML), + // TO FIX: Why the heck does this only include the first category? Category: catName, // TO FIX: Created should be first published Created: post.PublishedAt, @@ -431,7 +441,7 @@ func (b *Builder) renderTemplate(w io.Writer, name string, data interface{}) err func (b *Builder) writeUploads(ctx buildContext, uploads []models.Upload) error { for _, u := range uploads { - fullPath := filepath.Join(ctx.outDir, "uploads", u.Slug) + fullPath := filepath.Join(ctx.outDir, b.opts.BaseUploads, u.Slug) if err := os.MkdirAll(filepath.Dir(fullPath), 0755); err != nil { return err } @@ -459,3 +469,37 @@ func (b *Builder) writeUploads(ctx buildContext, uploads []models.Upload) error } return nil } + +func (b *Builder) writeStaticAssets(ctx buildContext) error { + return fs.WalkDir(b.opts.StaticFS, ".", func(path string, d os.DirEntry, err error) error { + if err != nil { + return err + } else if d.IsDir() { + return nil + } + + fullPath := filepath.Join(ctx.outDir, b.opts.BaseStatic, path) + if err := os.MkdirAll(filepath.Dir(fullPath), 0755); err != nil { + return err + } + + return func() error { + r, err := b.opts.StaticFS.Open(path) + if err != nil { + return err + } + defer r.Close() + + w, err := os.Create(fullPath) + if err != nil { + return err + } + defer w.Close() + + if _, err := io.Copy(w, r); err != nil { + return err + } + return nil + }() + }) +} diff --git a/providers/sitebuilder/tmpls.go b/providers/sitebuilder/tmpls.go index 2152290..cea02f5 100644 --- a/providers/sitebuilder/tmpls.go +++ b/providers/sitebuilder/tmpls.go @@ -29,12 +29,17 @@ const ( ) type Options struct { - // BasePosts is the base path for posts. - BasePosts string + BasePosts string // BasePosts is the base path for posts. + BaseUploads string // BaseUploads is the base path for uploads. + BaseStatic string // BaseStatic is the base path for static assets. // TemplatesFS provides the raw templates for rendering the site. TemplatesFS fs.FS + // StaticFS provides the raw assets for the site. This will be written as is + // from the BaseStatic dir. + StaticFS fs.FS + // FeedItems holds the number of posts to show in the feed. FeedItems int diff --git a/services/publisher/service.go b/services/publisher/service.go index 2ed9046..939817a 100644 --- a/services/publisher/service.go +++ b/services/publisher/service.go @@ -3,6 +3,7 @@ package publisher import ( "context" "io" + "io/fs" "iter" "log" "os" @@ -102,9 +103,22 @@ func (p *Publisher) publishSite(ctx context.Context, pubSite pubmodel.Site, targ renderTZ = time.UTC } + templateFS, err := fs.Sub(simplecss.FS, "templates") + if err != nil { + return err + } + + staticFS, err := fs.Sub(simplecss.FS, "static") + if err != nil { + return err + } + sb, err := sitebuilder.New(pubSite, sitebuilder.Options{ BasePosts: "/posts", - TemplatesFS: simplecss.FS, + BaseUploads: "/uploads", + BaseStatic: "/static", + TemplatesFS: templateFS, + StaticFS: staticFS, FeedItems: 30, RenderTZ: renderTZ, }) diff --git a/views/categories/edit.html b/views/categories/edit.html index c838778..c6c3606 100644 --- a/views/categories/edit.html +++ b/views/categories/edit.html @@ -1,6 +1,6 @@
-

{{ if .isNew }}New Category{{ else }}Edit Category{{ end }}

+
{{ if .isNew }}New Category{{ else }}Edit Category{{ end }}
{{ if .isNew }} @@ -10,27 +10,27 @@ {{ end }}
- +
- +
Auto-generated from name if left blank.
- +
Markdown supported. Displayed on the category archive page.
-
+
{{ if not .isNew }} diff --git a/views/categories/index.html b/views/categories/index.html index f768977..2d17beb 100644 --- a/views/categories/index.html +++ b/views/categories/index.html @@ -1,35 +1,32 @@
-

Categories

- - - - - - - - - - - {{ range .categories }} + {{ if .categories }} +
NameSlugPosts
+ - - - - + + + - {{ else }} - - - - {{ end }} - -
{{ .Name }}{{ .Slug }}{{ .PostCount }} - Edit - NameSlugPosts
No categories yet.
+ + + {{ range .categories }} + + {{ .Name }} + {{ .Slug }} + {{ .PostCount }} + + {{ end }} + + + {{ else }} +
+
📚
No categories yet.
+
+ {{ end }}
diff --git a/views/layouts/main.html b/views/layouts/main.html index 2b81177..908094f 100644 --- a/views/layouts/main.html +++ b/views/layouts/main.html @@ -7,7 +7,7 @@ - + {{ template "_common/nav" . }} {{ embed }} diff --git a/views/posts/edit.html b/views/posts/edit.html index 07be770..d162788 100644 --- a/views/posts/edit.html +++ b/views/posts/edit.html @@ -1,6 +1,6 @@ {{ $isPublished := ne .post.State 1 }}
-
@@ -10,9 +10,7 @@
-
- -
+
{{ if $isPublished }} diff --git a/views/posts/index.html b/views/posts/index.html index 3d2597f..bbf445d 100644 --- a/views/posts/index.html +++ b/views/posts/index.html @@ -28,12 +28,9 @@
{{ if eq $p.State 1 }} - {{ $.user.FormatTime $p.UpdatedAt }} Draft + Draft {{ else }} - {{ $.user.FormatTime $p.PublishedAt }} - {{ end }} - {{ range $p.Categories }} - {{ .Name }} + {{ end }}