Bootstrapped during the 2026-06-06 BlockNinja consolidation. Was previously an unversioned directory inside ~/src/blockninja-themes/magazine-bold. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
71 lines
1.8 KiB
Go
71 lines
1.8 KiB
Go
package main
|
|
|
|
import (
|
|
"bytes"
|
|
"context"
|
|
|
|
"git.dev.alexdunmow.com/block/core/blocks"
|
|
)
|
|
|
|
// PhotoEssayBlockMeta is the numbered photo-essay scaffolding.
|
|
var PhotoEssayBlockMeta = blocks.BlockMeta{
|
|
Key: "photo_essay",
|
|
Title: "Photo Essay",
|
|
Description: "Numbered photo-essay with asymmetric frame spans (half / full / tall) and mono captions.",
|
|
Source: "magazine-bold",
|
|
Category: blocks.CategoryContent,
|
|
}
|
|
|
|
// PhotoFrame is a single image in the photo essay.
|
|
type PhotoFrame struct {
|
|
Number int
|
|
Image string
|
|
Caption string
|
|
Span string
|
|
}
|
|
|
|
// PhotoEssayData is what the templ component consumes.
|
|
type PhotoEssayData struct {
|
|
Title string
|
|
Frames []PhotoFrame
|
|
}
|
|
|
|
// PhotoEssayBlock renders the photo essay scaffolding.
|
|
// content keys: title (text), frames (collection of {image, caption, span}).
|
|
func PhotoEssayBlock(ctx context.Context, content map[string]any) string {
|
|
rawFrames := getSlice(content, "frames")
|
|
frames := make([]PhotoFrame, 0, len(rawFrames))
|
|
for i, item := range rawFrames {
|
|
img := blocks.ResolveMediaPath(getString(item, "image"))
|
|
// Skip frames that have no image (malformed-content safety).
|
|
if img == "" {
|
|
continue
|
|
}
|
|
frames = append(frames, PhotoFrame{
|
|
Number: i + 1,
|
|
Image: img,
|
|
Caption: getString(item, "caption"),
|
|
Span: normalizeSpan(getString(item, "span")),
|
|
})
|
|
}
|
|
data := PhotoEssayData{
|
|
Title: getString(content, "title"),
|
|
Frames: frames,
|
|
}
|
|
var buf bytes.Buffer
|
|
_ = photoEssayComponent(data).Render(ctx, &buf)
|
|
return buf.String()
|
|
}
|
|
|
|
// photoFrameSpanClass maps a span string to its CSS utility class.
|
|
func photoFrameSpanClass(span string) string {
|
|
switch span {
|
|
case "full":
|
|
return "mb-frame-full"
|
|
case "tall":
|
|
return "mb-frame-tall"
|
|
default:
|
|
return "mb-frame-half"
|
|
}
|
|
}
|