diff --git a/config/config.go b/config/config.go index 518e082..643334e 100644 --- a/config/config.go +++ b/config/config.go @@ -10,6 +10,7 @@ type Config struct { NetlifyAuthToken string `env:"NETLIFY_AUTH_TOKEN"` DataDir string `env:"DATA_DIR"` EncryptedCookieKey string `env:"ENCRYPTED_COOKIE_KEY"` + BaseURL string `env:"BASE_URL,default=http://localhost:3000/"` DataStagingDir string `env:"DATA_STAGING_DIR,default=staging"` DataScratchDir string `env:"DATA_SCRATCH_DIR,default=scratch"` diff --git a/main.go b/main.go index fea03d0..6d4da92 100644 --- a/main.go +++ b/main.go @@ -72,7 +72,7 @@ func main() { return } - hugoProvider, err := hugo.New(cfg.StagingDir(), cfg.PreviewDir(), cfg.ScratchDir()) + hugoProvider, err := hugo.New(cfg.StagingDir(), cfg.BaseURL, cfg.PreviewDir(), cfg.ScratchDir()) if err != nil { log.Fatal(err) } diff --git a/providers/hugo/provider.go b/providers/hugo/provider.go index 0cf94be..2860c3a 100644 --- a/providers/hugo/provider.go +++ b/providers/hugo/provider.go @@ -2,26 +2,33 @@ package hugo import ( "context" - "fmt" "gopkg.in/yaml.v3" "lmika.dev/lmika/hugo-cms/models" "log" + "net/url" "os" "os/exec" "path/filepath" ) type Provider struct { - stagingDir string - previewDir string - scratchDir string + stagingDir string + previewDir string + previewBaseURL *url.URL + scratchDir string } -func New(stagingDir, previewDir, scratchDir string) (*Provider, error) { +func New(stagingDir, previewBaseURL, previewDir, scratchDir string) (*Provider, error) { + baseURL, err := url.Parse(previewBaseURL) + if err != nil { + return nil, err + } + return &Provider{ - stagingDir: stagingDir, - previewDir: previewDir, - scratchDir: scratchDir, + stagingDir: stagingDir, + previewBaseURL: baseURL, + previewDir: previewDir, + scratchDir: scratchDir, }, nil } @@ -51,8 +58,12 @@ func (p *Provider) NewSite(ctx context.Context, site models.Site) error { } func (p *Provider) PreviewSite(ctx context.Context, site models.Site) (outDir string, err error) { + previewURL, err := p.previewBaseURL.Parse("preview/" + site.Name) + if err != nil { + return "", err + } previewTarget := models.PublishTarget{ - URL: fmt.Sprintf("http://localhost:3000/preview/%s", site.Name), + URL: previewURL.String(), } return p.publishSiteAt(ctx, p.previewDir, site, previewTarget, "hugoPreview.yaml") @@ -80,6 +91,7 @@ func (p *Provider) publishSiteAt(ctx context.Context, dir string, site models.Si cmd := exec.CommandContext(ctx, "hugo", "--source", baseSiteDir, "--destination", outDir, + "--quiet", "--config", filepath.Join(baseSiteDir, configFile), "--baseURL", target.URL) cmd.Stderr = os.Stderr @@ -91,12 +103,11 @@ func (p *Provider) publishSiteAt(ctx context.Context, dir string, site models.Si return outDir, nil } -func (p *Provider) ReconfigureSite(ctx context.Context, configBase string, site models.Site) error { +func (p *Provider) ReconfigureSite(ctx context.Context, isPreviewConfig bool, configBase string, site models.Site) error { hugoCfg := hugoConfig{ Title: site.Title, LanguageCode: "en", Theme: site.Theme, - CanonifyURLs: configBase == "hugoPreview", Markup: hugoConfigMarkup{ Goldmark: hugoGoldmarkConfig{ Renderer: hugoGoldmarkRendererConfig{ @@ -106,6 +117,10 @@ func (p *Provider) ReconfigureSite(ctx context.Context, configBase string, site }, } + if isPreviewConfig { + hugoCfg.CanonifyURLs = true + } + ymlBytes, err := yaml.Marshal(hugoCfg) if err != nil { return err diff --git a/services/sitebuilder/service.go b/services/sitebuilder/service.go index 929af90..7ba2280 100644 --- a/services/sitebuilder/service.go +++ b/services/sitebuilder/service.go @@ -172,11 +172,11 @@ func (s *Service) createSite(ctx context.Context, site models.Site) error { return err } - if err := s.hugo.ReconfigureSite(ctx, "hugo", site); err != nil { + if err := s.hugo.ReconfigureSite(ctx, false, "hugo", site); err != nil { return err } - if err := s.hugo.ReconfigureSite(ctx, "hugoPreview", site); err != nil { + if err := s.hugo.ReconfigureSite(ctx, true, "hugoPreview", site); err != nil { return err } diff --git a/services/sites/service.go b/services/sites/service.go index 9380ff1..8ad2bd7 100644 --- a/services/sites/service.go +++ b/services/sites/service.go @@ -61,26 +61,28 @@ func (s *Service) SaveSettings(ctx context.Context, site models.Site, newSetting return err } - pubTarget, err := s.db.GetPublishTargetBySiteRole(ctx, newSite.ID, models.TargetRoleProduction) - if err == nil { - pubTarget.TargetRef = newSettings.TargetRef - pubTarget.URL = newSettings.TargetURL - if err := s.db.UpdatePublishTarget(ctx, pubTarget); err != nil { + if newSettings.TargetRef != "" && newSettings.TargetURL != "" { + pubTarget, err := s.db.GetPublishTargetBySiteRole(ctx, newSite.ID, models.TargetRoleProduction) + if err == nil { + pubTarget.TargetRef = newSettings.TargetRef + pubTarget.URL = newSettings.TargetURL + if err := s.db.UpdatePublishTarget(ctx, pubTarget); err != nil { + return err + } + } else if errors.Is(err, pgx.ErrNoRows) { + pubTarget = models.PublishTarget{ + SiteID: newSite.ID, + Role: models.TargetRoleProduction, + Type: models.TargetTypeNetlify, + URL: newSettings.TargetURL, + TargetRef: newSettings.TargetRef, + } + if err := s.db.InsertPublishTarget(ctx, &pubTarget); err != nil { + return err + } + } else { return err } - } else if errors.Is(err, pgx.ErrNoRows) { - pubTarget = models.PublishTarget{ - SiteID: newSite.ID, - Role: models.TargetRoleProduction, - Type: models.TargetTypeNetlify, - URL: newSettings.TargetURL, - TargetRef: newSettings.TargetRef, - } - if err := s.db.InsertPublishTarget(ctx, &pubTarget); err != nil { - return err - } - } else { - return err } return s.jobs.Queue(ctx, s.sb.RebuildSite(site, newSite)) diff --git a/sql/schema/1_init.up.sql b/sql/schema/1_init.up.sql index 772df25..ab6f576 100644 --- a/sql/schema/1_init.up.sql +++ b/sql/schema/1_init.up.sql @@ -3,6 +3,10 @@ CREATE TYPE post_state AS ENUM ( 'published' ); +CREATE TYPE post_format AS ENUM ( + 'markdown' +); + CREATE TYPE target_role AS ENUM ( 'production' ); @@ -49,16 +53,17 @@ CREATE TABLE post_types ( ); CREATE TABLE posts ( - id BIGSERIAL NOT NULL PRIMARY KEY, - site_id BIGINT NOT NULL, + id BIGSERIAL NOT NULL PRIMARY KEY, + site_id BIGINT NOT NULL, title TEXT, post_type_id BIGINT, - body TEXT NOT NULL, - state post_state NOT NULL, - props JSON NOT NULL, + format post_format NOT NULL DEFAULT 'markdown', + body TEXT NOT NULL, + state post_state NOT NULL, + props JSON NOT NULL, publish_date TIMESTAMP WITH TIME ZONE, - created_at TIMESTAMP NOT NULL, - updated_at TIMESTAMP NOT NULL, + created_at TIMESTAMP NOT NULL, + updated_at TIMESTAMP NOT NULL, FOREIGN KEY (post_type_id) REFERENCES post_types (id) ON DELETE CASCADE, FOREIGN KEY (site_id) REFERENCES sites (id) ON DELETE CASCADE @@ -80,6 +85,7 @@ CREATE TABLE pages ( bundle_id BIGINT NOT NULL, name TEXT NOT NULL, name_provenance page_name_provenance NOT NULL, + format post_format NOT NULL DEFAULT 'markdown', title TEXT, post_type_id BIGINT, body TEXT NOT NULL, diff --git a/templates/layouts/site.html b/templates/layouts/site.html index 45bd5dc..81536c4 100644 --- a/templates/layouts/site.html +++ b/templates/layouts/site.html @@ -14,6 +14,7 @@