MediaValue gains an Attribution credit resolved through the existing MediaResolver context hook. The BlockNote image case renders width and align presets, alt text, an optional link wrap, and the attribution chip in chip, chipHover, and below modes with the same themed markup as the cms page-builder image block. Legacy url-and-caption blocks render byte-identical to the previous output. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
86 lines
2.9 KiB
Go
86 lines
2.9 KiB
Go
package blocks
|
|
|
|
import (
|
|
"fmt"
|
|
"html"
|
|
)
|
|
|
|
// MediaValue represents a rich media object for template substitution.
|
|
// Implements fmt.Stringer to render a full <img> tag when used directly.
|
|
type MediaValue struct {
|
|
Src string // Full URL path (e.g., "/media/uuid/webp.webp")
|
|
Alt string // Alt text from media library
|
|
Filename string // Original filename
|
|
Width int // Image width in pixels
|
|
Height int // Image height in pixels
|
|
// Attribution is the stock-source credit (Pexels import), nil for
|
|
// ordinary uploads. JSON tags mirror the CMS media row's attribution JSONB.
|
|
Attribution *MediaAttribution
|
|
}
|
|
|
|
// MediaAttribution is the stock-source credit for imported media.
|
|
type MediaAttribution struct {
|
|
Source string `json:"source"`
|
|
SourceURL string `json:"source_url"`
|
|
Photographer string `json:"photographer"`
|
|
PhotographerURL string `json:"photographer_url"`
|
|
}
|
|
|
|
// String renders the default <img> tag representation.
|
|
func (m MediaValue) String() string {
|
|
attrs := fmt.Sprintf(`src="%s" alt="%s" class="w-full h-auto"`,
|
|
html.EscapeString(m.Src),
|
|
html.EscapeString(m.Alt))
|
|
if m.Width > 0 && m.Height > 0 {
|
|
attrs += fmt.Sprintf(` width="%d" height="%d"`, m.Width, m.Height)
|
|
}
|
|
return fmt.Sprintf(`<img %s>`, attrs)
|
|
}
|
|
|
|
// RenderWithClass renders the <img> tag with custom CSS classes.
|
|
func (m MediaValue) RenderWithClass(class string) string {
|
|
attrs := fmt.Sprintf(`src="%s" alt="%s" class="%s"`,
|
|
html.EscapeString(m.Src),
|
|
html.EscapeString(m.Alt),
|
|
html.EscapeString(class))
|
|
if m.Width > 0 && m.Height > 0 {
|
|
attrs += fmt.Sprintf(` width="%d" height="%d"`, m.Width, m.Height)
|
|
}
|
|
return fmt.Sprintf(`<img %s>`, attrs)
|
|
}
|
|
|
|
// TemplateRenderer is the interface for rendering pongo2/Jinja2-style templates.
|
|
// The CMS registers an implementation at startup.
|
|
type TemplateRenderer interface {
|
|
RenderTemplate(tmpl string, data map[string]any) (string, error)
|
|
ProcessIcons(html string) string
|
|
}
|
|
|
|
// templateRenderer holds the registered template renderer.
|
|
var templateRenderer TemplateRenderer
|
|
|
|
// RegisterTemplateRenderer sets the global template renderer.
|
|
// Called by the CMS at startup to provide pongo2 rendering.
|
|
func RegisterTemplateRenderer(r TemplateRenderer) {
|
|
templateRenderer = r
|
|
}
|
|
|
|
// RenderTemplate renders a pongo2/Jinja2-style template string with the given data.
|
|
// Returns the rendered HTML or an error. Falls back to a no-op if no renderer is registered.
|
|
func RenderTemplate(tmpl string, data map[string]any) (string, error) {
|
|
if templateRenderer == nil {
|
|
// No renderer registered — return template as-is (no variable substitution)
|
|
return tmpl, nil
|
|
}
|
|
return templateRenderer.RenderTemplate(tmpl, data)
|
|
}
|
|
|
|
// ProcessIcons processes ::pack:name:: icon syntax in HTML.
|
|
// Returns the HTML with icons replaced, or the original if no renderer is registered.
|
|
func ProcessIcons(htmlStr string) string {
|
|
if templateRenderer == nil {
|
|
return htmlStr
|
|
}
|
|
return templateRenderer.ProcessIcons(htmlStr)
|
|
}
|