Started working on pages

This commit is contained in:
Leon Mika 2025-02-16 11:43:22 +11:00
parent e2f159e980
commit ba12398d2f
30 changed files with 1391 additions and 145 deletions

View file

@ -0,0 +1,105 @@
package sitebuilder
import (
"context"
"fmt"
"lmika.dev/lmika/hugo-cms/models"
"lmika.dev/pkg/modash/momap"
"os"
"time"
)
func (s *Service) WritePage(site models.Site, bundle models.Bundle, page models.Page) models.Job {
return models.Job{
Do: func(ctx context.Context) error {
s.signalSiteBuildingStarted(ctx, site)
defer s.signalSiteBuildingFinished(ctx, site)
rbn, err := s.fullRebuildNecessary(ctx, site)
if err != nil {
return err
} else if rbn {
return s.rebuildSite(ctx, site, site)
}
themeMeta, ok := s.themes.Lookup(site.Theme)
if !ok {
return fmt.Errorf("theme %s not found in themes", site.Theme)
}
if err := s.writePage(site, themeMeta, bundle, page); err != nil {
return err
}
return s.publish(ctx, site)
},
}
}
func (s *Service) DeletePage(site models.Site, page models.Page) models.Job {
return models.Job{
Do: func(ctx context.Context) error {
s.signalSiteBuildingStarted(ctx, site)
defer s.signalSiteBuildingFinished(ctx, site)
bundle, err := s.db.GetBundleWithID(ctx, page.BundleID)
if err != nil {
return err
}
postFilename := s.pageFilename(site, bundle, page)
if os.Remove(postFilename) != nil {
return nil
}
// TODO: if dir is empty, delete it
return s.publish(ctx, site)
},
}
}
func (s *Service) writeAllPages(ctx context.Context, site models.Site) error {
themeMeta, ok := s.themes.Lookup(site.Theme)
if !ok {
return fmt.Errorf("theme %s not found in themes", site.Theme)
}
bundles, err := s.db.ListBundles(ctx, site.ID)
if err != nil {
return err
}
bundlesByID := momap.FromSlice(bundles, func(b models.Bundle) (int64, models.Bundle) { return b.ID, b })
var startId int64
for {
pages, err := s.db.ListPublishablePages(ctx, int64(startId), site.ID)
if err != nil {
return err
} else if len(pages) == 0 {
return nil
}
for _, page := range pages {
if err := s.writePage(site, themeMeta, bundlesByID[page.BundleID], page); err != nil {
return err
}
}
startId = pages[len(pages)-1].ID
}
}
func (s *Service) writePage(site models.Site, themeMeta models.ThemeMeta, bundle models.Bundle, page models.Page) error {
postFilename := s.pageFilename(site, bundle, page)
frontMatter := map[string]any{
"date": page.PublishDate.Format(time.RFC3339),
}
if page.Title != "" {
frontMatter["title"] = page.Title
} else if themeMeta.PreferTitle {
frontMatter["title"] = page.PublishDate.Format(time.ANSIC)
}
return s.writeMarkdownFile(postFilename, frontMatter, page.Body)
}

View file

@ -6,7 +6,6 @@ import (
"gopkg.in/yaml.v3"
"lmika.dev/lmika/hugo-cms/models"
"lmika.dev/lmika/hugo-cms/providers/hugo"
"log"
"os"
"path/filepath"
"time"
@ -104,19 +103,21 @@ func (s *Service) writePost(site models.Site, post models.Post) error {
postFilename := s.postFilename(site, themeMeta, post)
log.Printf(" .. post %v", postFilename)
if err := os.MkdirAll(filepath.Dir(postFilename), 0755); err != nil {
return err
}
frontMatter := map[string]string{
"date": post.PostDate.Format(time.RFC3339),
frontMatter := map[string]any{
"date": post.PublishDate.Format(time.RFC3339),
}
if post.Title != "" {
frontMatter["title"] = post.Title
} else if themeMeta.PreferTitle {
frontMatter["title"] = post.PostDate.Format(time.ANSIC)
frontMatter["title"] = post.PublishDate.Format(time.ANSIC)
}
return s.writeMarkdownFile(postFilename, frontMatter, post.Body)
}
func (s *Service) writeMarkdownFile(outFile string, frontMatter map[string]any, body string) error {
if err := os.MkdirAll(filepath.Dir(outFile), 0755); err != nil {
return err
}
fmBytes, err := yaml.Marshal(frontMatter)
@ -124,7 +125,7 @@ func (s *Service) writePost(site models.Site, post models.Post) error {
return err
}
f, err := os.Create(postFilename)
f, err := os.Create(outFile)
if err != nil {
return err
}
@ -139,7 +140,7 @@ func (s *Service) writePost(site models.Site, post models.Post) error {
if _, err := f.WriteString("---\n"); err != nil {
return err
}
if _, err := f.WriteString(post.Body); err != nil {
if _, err := f.WriteString(body); err != nil {
return err
}
@ -147,5 +148,15 @@ func (s *Service) writePost(site models.Site, post models.Post) error {
}
func (s *Service) postFilename(site models.Site, themeMeta models.ThemeMeta, post models.Post) string {
return filepath.Join(s.hugo.SiteStagingDir(site, hugo.ContentSiteDir), themeMeta.PostDir, post.CreatedAt.Format("2006-01-02-150405.md"))
return filepath.Join(s.hugo.SiteStagingDir(site, hugo.ContentSiteDir), themeMeta.BlogPostBundle, post.CreatedAt.Format("2006-01-02-150405.md"))
}
func (s *Service) pageFilename(site models.Site, bundle models.Bundle, page models.Page) string {
bundleDir := ""
if bundle.Name != models.RootBundleName {
bundleDir = bundle.Name
}
pageName := page.Name + ".md"
return filepath.Join(s.hugo.SiteStagingDir(site, hugo.ContentSiteDir), bundleDir, pageName)
}

View file

@ -79,6 +79,10 @@ func (s *Service) rebuildSite(ctx context.Context, oldSite, newSite models.Site)
return err
}
if err := s.writeAllPages(ctx, newSite); err != nil {
return err
}
return s.publish(ctx, newSite)
}
@ -148,3 +152,4 @@ func (s *Service) signalSiteBuildingStarted(ctx context.Context, site models.Sit
func (s *Service) signalSiteBuildingFinished(ctx context.Context, site models.Site) {
s.bus.Fire(models.Event{Type: models.EventSiteBuildingDone, Data: site})
}

View file

@ -0,0 +1,32 @@
package sitebuilder
import (
"lmika.dev/lmika/hugo-cms/models"
"lmika.dev/lmika/hugo-cms/providers/bus"
)
type SiteBuildingTracker struct {
bus *bus.Bus
isBuildingState map[int64]models.Site
}
func NewSiteBuildingTracker(bus *bus.Bus) *SiteBuildingTracker {
return &SiteBuildingTracker{
bus: bus,
isBuildingState: map[int64]models.Site{},
}
}
func (sbt *SiteBuildingTracker) Listen() {
sub := sbt.bus.Subscribe()
for e := range sub.C {
switch e.Type {
case models.EventSiteBuildingStart:
site := e.Data.(models.Site)
sbt.isBuildingState[site.ID] = site
case models.EventSiteBuildingDone:
delete(sbt.isBuildingState, e.Data.(models.Site).ID)
}
}
}