This will generate a local version of the Hugo site and serve it via the server
147 lines
3.2 KiB
Go
147 lines
3.2 KiB
Go
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)
|
|
}
|
|
|
|
bundleInfo, err := s.db.GetSiteBundleInfo(ctx, site.ID)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
if err := s.writePage(pageBuildInfo{
|
|
site: site,
|
|
themeMeta: themeMeta,
|
|
bundle: bundle,
|
|
bundleInfo: bundleInfo,
|
|
}, 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
|
|
}
|
|
|
|
themeMeta, ok := s.themes.Lookup(site.Theme)
|
|
if !ok {
|
|
return fmt.Errorf("theme %s not found in themes", site.Theme)
|
|
}
|
|
|
|
bundleInfo, err := s.db.GetSiteBundleInfo(ctx, site.ID)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
postFilename := s.pageFilename(pageBuildInfo{
|
|
site: site,
|
|
themeMeta: themeMeta,
|
|
bundle: bundle,
|
|
bundleInfo: bundleInfo,
|
|
}, 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 })
|
|
|
|
bundleInfo, err := s.db.GetSiteBundleInfo(ctx, site.ID)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
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(pageBuildInfo{
|
|
site: site,
|
|
themeMeta: themeMeta,
|
|
bundle: bundlesByID[page.BundleID],
|
|
bundleInfo: bundleInfo,
|
|
}, page); err != nil {
|
|
return err
|
|
}
|
|
}
|
|
startId = pages[len(pages)-1].ID
|
|
}
|
|
}
|
|
|
|
func (s *Service) writePage(bi pageBuildInfo, page models.Page) error {
|
|
postFilename := s.pageFilename(bi, page)
|
|
|
|
frontMatter := map[string]any{
|
|
"date": page.PublishDate.Format(time.RFC3339),
|
|
}
|
|
|
|
if page.Title != "" {
|
|
frontMatter["title"] = page.Title
|
|
}
|
|
|
|
return s.writeMarkdownFile(postFilename, frontMatter, page.Body)
|
|
}
|
|
|
|
type pageBuildInfo struct {
|
|
site models.Site
|
|
themeMeta models.ThemeMeta
|
|
bundle models.Bundle
|
|
bundleInfo map[int64]models.BundleInfo
|
|
}
|