2
0

feat(pages): add gallery section to landing page templates

Add configurable gallery section that displays images from repository's .gallery folder on landing pages. Includes settings for enabled/disabled, headline, subheadline, max images (default 6), and grid columns (default 3). Reads captions from gallery.json metadata. Implements gallery rendering in all four page templates (bold-marketing, minimalist-docs, open-source-hero, saas-conversion). Integrates with existing gallery management feature.
This commit is contained in:
2026-03-15 22:54:11 -04:00
parent fc86952bf4
commit 679810687f
10 changed files with 263 additions and 0 deletions

View File

@@ -23,6 +23,7 @@ import (
"code.gitcaddy.com/server/v3/models/renderhelper"
repo_model "code.gitcaddy.com/server/v3/models/repo"
"code.gitcaddy.com/server/v3/modules/git"
"code.gitcaddy.com/server/v3/modules/gitrepo"
"code.gitcaddy.com/server/v3/modules/json"
"code.gitcaddy.com/server/v3/modules/log"
"code.gitcaddy.com/server/v3/modules/markup/markdown"
@@ -196,6 +197,14 @@ func renderLandingPage(ctx *context.Context, repo *repo_model.Repository, config
}
}
// Load gallery images if gallery section is enabled
if config.Gallery.Enabled {
images := loadGalleryImagesForLanding(ctx, repo, config)
if len(images) > 0 {
ctx.Data["GalleryImages"] = images
}
}
tpl := selectTemplate(config.Template)
ctx.HTML(http.StatusOK, tpl)
}
@@ -315,6 +324,94 @@ func getPageTitle(repo *repo_model.Repository, config *pages_module.LandingConfi
return repo.Name
}
// GalleryImageInfo holds gallery image data for landing page templates
type GalleryImageInfo struct {
Name string
Caption string
URL string
}
// loadGalleryImagesForLanding reads gallery images from the .gallery folder
func loadGalleryImagesForLanding(ctx *context.Context, repo *repo_model.Repository, config *pages_module.LandingConfig) []GalleryImageInfo {
if repo.IsEmpty {
return nil
}
gitRepo, err := gitrepo.RepositoryFromRequestContextOrOpen(ctx, repo)
if err != nil {
return nil
}
commit, err := gitRepo.GetBranchCommit(repo.DefaultBranch)
if err != nil {
return nil
}
galleryEntry, err := commit.GetTreeEntryByPath(".gallery")
if err != nil || !galleryEntry.IsDir() {
return nil
}
// Load metadata for captions
var metadata struct {
Images []struct {
Name string `json:"name"`
Caption string `json:"caption"`
} `json:"images"`
}
if entry, err := commit.GetTreeEntryByPath(".gallery/gallery.json"); err == nil {
if content, err := entry.Blob().GetBlobContent(100000); err == nil {
_ = json.Unmarshal([]byte(content), &metadata)
}
}
captionMap := make(map[string]string)
for _, img := range metadata.Images {
captionMap[img.Name] = img.Caption
}
tree, err := commit.SubTree(".gallery")
if err != nil {
return nil
}
entries, err := tree.ListEntries()
if err != nil {
return nil
}
maxImages := config.Gallery.MaxImages
if maxImages <= 0 {
maxImages = 6
}
var images []GalleryImageInfo
for _, entry := range entries {
if entry.IsDir() {
continue
}
name := entry.Name()
if name == "gallery.json" {
continue
}
ext := strings.ToLower(path.Ext(name))
switch ext {
case ".png", ".jpg", ".jpeg", ".gif", ".webp", ".svg", ".bmp":
default:
continue
}
images = append(images, GalleryImageInfo{
Name: name,
Caption: captionMap[name],
URL: repo.Link() + "/raw/" + repo.DefaultBranch + "/.gallery/" + name,
})
if len(images) >= maxImages {
break
}
}
return images
}
// loadReadmeContent loads and renders the README content
func loadReadmeContent(ctx *context.Context, repo *repo_model.Repository) (template.HTML, error) {
gitRepo, err := git.OpenRepository(ctx, repo.RepoPath())

View File

@@ -545,6 +545,15 @@ func PagesContentPost(ctx *context.Context) {
if maxPosts := ctx.FormInt("blog_max_posts"); maxPosts > 0 {
config.Blog.MaxPosts = maxPosts
}
config.Gallery.Enabled = ctx.FormBool("gallery_enabled")
config.Gallery.Headline = ctx.FormString("gallery_headline")
config.Gallery.Subheadline = ctx.FormString("gallery_subheadline")
if maxImages := ctx.FormInt("gallery_max_images"); maxImages > 0 {
config.Gallery.MaxImages = maxImages
}
if cols := ctx.FormInt("gallery_columns"); cols >= 2 && cols <= 4 {
config.Gallery.Columns = cols
}
config.Stats = nil
for i := range 10 {
value := ctx.FormString(fmt.Sprintf("stat_value_%d", i))