// Code generated by templ - DO NOT EDIT. // templ: version: v0.3.1020 package bn //lint:file-ignore SA4006 This context is only used if a nested component is present. import "github.com/a-h/templ" import templruntime "github.com/a-h/templ/runtime" import ( "strings" "time" "github.com/google/uuid" ) // resolveMediaURL converts media: prefixed URLs to proper /media/ paths // e.g., "media:abc/image.webp" → "/media/abc/image.webp" func resolveMediaURL(url string) string { if strings.HasPrefix(url, "media:") { return "/media/" + strings.TrimPrefix(url, "media:") } return url } // canonicalURL resolves the canonical link. An admin-set value wins (made absolute // against the page's own origin when it is root-relative); otherwise the page's own // absolute URL is used as a self-referencing canonical. Returns "" only when neither // is available. func canonicalURL(canonical, pageURL string) string { if canonical == "" { return pageURL } if strings.HasPrefix(canonical, "http://") || strings.HasPrefix(canonical, "https://") { return canonical } if strings.HasPrefix(canonical, "/") && pageURL != "" { if i := strings.Index(pageURL, "://"); i >= 0 { if j := strings.IndexByte(pageURL[i+3:], '/'); j >= 0 { return pageURL[:i+3+j] + canonical } return pageURL + canonical } } return canonical } // BrandingData contains generated favicon/icon URLs type BrandingData struct { FaviconICO string // /.brand/{id}/favicon.ico Favicon16 string // /.brand/{id}/favicon-16x16.png Favicon32 string // /.brand/{id}/favicon-32x32.png Favicon96 string // /.brand/{id}/favicon-96x96.png AppleTouchIcon string // /.brand/{id}/apple-touch-icon.png (180x180) Android192 string // /.brand/{id}/android-chrome-192x192.png Android512 string // /.brand/{id}/android-chrome-512x512.png Maskable512 string // /.brand/{id}/maskable-512x512.png Master1024 string // /.brand/{id}/icon-1024x1024.png ManifestURL string // /.brand/{id}/site.webmanifest MaskIcon string // /.brand/{id}/mask-icon.svg MSTile150 string // /.brand/{id}/mstile-150x150.png BrowserConfig string // /.brand/{id}/browserconfig.xml ThemeColor string SVG string // Optional SVG pass-through IsGenerated bool } // CustomScriptEntry represents a single custom script with placement control type CustomScriptEntry struct { Name string Placement string // "head" or "body" Code string Enabled bool } // SiteSettingsData contains site-wide settings for head injection type SiteSettingsData struct { Title string Description string Favicon string Logo string LogoAlt string AppleTouchIcon string GoogleAnalyticsID string CustomScripts []CustomScriptEntry GoogleAnalyticsEnabled bool GoogleAnalyticsExplicitlySet bool // true if the enabled flag was explicitly set in JSON (not nil) MetaDescription string DefaultOGImage string TwitterHandle string OGSiteName string Branding BrandingData AdminBypassMode string // "maintenance", "coming_soon", or "" if not bypassing Toolbar ToolbarData LLMsTxtEnabled bool // Whether llms.txt is enabled for AI content discovery RSSFeedURL string // URL to the RSS feed (e.g., "/rss"), empty to disable RSSFeedTitle string // Feed title for discovery link } // PageMeta contains page-level SEO meta data (overrides site defaults) type PageMeta struct { MetaTitle string // Custom SEO title (overrides page title) MetaDescription string // Page-specific meta description OGTitle string // Open Graph title OGDescription string // Open Graph description OGImage string // Open Graph image URL TwitterTitle string // Twitter card title TwitterDescription string // Twitter card description TwitterImage string // Twitter card image URL CanonicalURL string // Canonical URL for this page RobotsDirective string // Robots directive (e.g., "noindex, nofollow") OGType string // Open Graph type ("article" for posts, else "website") PageURL string // Absolute URL of this page (og:url + auto-canonical) ArticlePublishedTime string // ISO 8601 published time (articles only) ArticleAuthor string // Author name (articles only) } // HeadData contains all data needed to render the element type HeadData struct { Title string Settings SiteSettingsData PageMeta PageMeta // Page-level SEO overrides ThemeCSS string ThemeMode string // "light", "dark", or "system" PluginStyles []string // Additional stylesheet URLs StructuredData string // JSON-LD structured data CSSHash string // Cache-busting hash for styles.css PageviewNonce string // Unique nonce for pageview deduplication EngagementConfig EngagementConfig // Engagement tracking config (for blog posts) } // ParseEngagementConfig extracts engagement config from the document map func ParseEngagementConfig(doc map[string]any) EngagementConfig { config := EngagementConfig{} engData, ok := doc["engagement_config"].(map[string]any) if !ok { return config } if v, ok := engData["page_path"].(string); ok { config.PagePath = v } if v, ok := engData["page_id"].(string); ok { config.PageID = v } if v, ok := engData["post_word_count"].(int); ok { config.PostWordCount = v } if v, ok := engData["session_id"].(string); ok { config.SessionID = v } if v, ok := engData["visitor_hash"].(string); ok { config.VisitorHash = v } if v, ok := engData["is_post"].(bool); ok { config.IsPost = v } return config } // ParseSiteSettings extracts site settings from the document map func ParseSiteSettings(doc map[string]any) SiteSettingsData { settings := SiteSettingsData{} siteData, ok := doc["site_settings"].(map[string]any) if !ok { return settings } if v, ok := siteData["title"].(string); ok { settings.Title = v } if v, ok := siteData["description"].(string); ok { settings.Description = v } if v, ok := siteData["favicon"].(string); ok { settings.Favicon = v } if v, ok := siteData["logo"].(string); ok { settings.Logo = v } if v, ok := siteData["logo_alt"].(string); ok { settings.LogoAlt = v } if v, ok := siteData["apple_touch_icon"].(string); ok { settings.AppleTouchIcon = v } // SEO defaults if seoData, ok := siteData["seo_defaults"].(map[string]any); ok { if v, ok := seoData["meta_description"].(string); ok { settings.MetaDescription = v } if v, ok := seoData["default_og_image"].(string); ok { settings.DefaultOGImage = v } if v, ok := seoData["twitter_handle"].(string); ok { settings.TwitterHandle = v } if v, ok := seoData["og_site_name"].(string); ok { settings.OGSiteName = v } } // Analytics var legacyHeadScripts, legacyBodyScripts string if analyticsData, ok := siteData["analytics"].(map[string]any); ok { if v, ok := analyticsData["google_analytics_id"].(string); ok { settings.GoogleAnalyticsID = v } // Read GA enabled flag — if present, use it; if absent but ID is set, default to enabled (backward compat) if v, ok := analyticsData["google_analytics_enabled"].(bool); ok { settings.GoogleAnalyticsEnabled = v settings.GoogleAnalyticsExplicitlySet = true } else if settings.GoogleAnalyticsID != "" { settings.GoogleAnalyticsEnabled = true } // Preserve legacy flat fields for fallback if v, ok := analyticsData["custom_head_scripts"].(string); ok { legacyHeadScripts = v } if v, ok := analyticsData["custom_body_scripts"].(string); ok { legacyBodyScripts = v } } // Structured custom scripts if scriptsArr, ok := siteData["custom_scripts"].([]any); ok && len(scriptsArr) > 0 { for _, item := range scriptsArr { entry, ok := item.(map[string]any) if !ok { continue } cs := CustomScriptEntry{} if v, ok := entry["name"].(string); ok { cs.Name = v } // Placement: proto enum stored as float64 (1=head, 2=body) or string switch p := entry["placement"].(type) { case float64: if p == 1 { cs.Placement = "head" } else if p == 2 { cs.Placement = "body" } case string: cs.Placement = p } if v, ok := entry["code"].(string); ok { cs.Code = v } if v, ok := entry["enabled"].(bool); ok { cs.Enabled = v } settings.CustomScripts = append(settings.CustomScripts, cs) } } // Fallback: if no structured scripts, migrate old flat fields if len(settings.CustomScripts) == 0 { if legacyHeadScripts != "" { settings.CustomScripts = append(settings.CustomScripts, CustomScriptEntry{ Name: "Legacy Head Scripts", Placement: "head", Code: legacyHeadScripts, Enabled: true, }) } if legacyBodyScripts != "" { settings.CustomScripts = append(settings.CustomScripts, CustomScriptEntry{ Name: "Legacy Body Scripts", Placement: "body", Code: legacyBodyScripts, Enabled: true, }) } } // Branding (generated favicons) if brandingData, ok := siteData["branding"].(map[string]any); ok { if v, ok := brandingData["is_generated"].(bool); ok { settings.Branding.IsGenerated = v } if v, ok := brandingData["favicon_ico"].(string); ok { settings.Branding.FaviconICO = v } if v, ok := brandingData["favicon_16"].(string); ok { settings.Branding.Favicon16 = v } if v, ok := brandingData["favicon_32"].(string); ok { settings.Branding.Favicon32 = v } if v, ok := brandingData["apple_touch_icon"].(string); ok { settings.Branding.AppleTouchIcon = v } if v, ok := brandingData["android_192"].(string); ok { settings.Branding.Android192 = v } if v, ok := brandingData["android_512"].(string); ok { settings.Branding.Android512 = v } if v, ok := brandingData["maskable_512"].(string); ok { settings.Branding.Maskable512 = v } if v, ok := brandingData["master_1024"].(string); ok { settings.Branding.Master1024 = v } if v, ok := brandingData["manifest_url"].(string); ok { settings.Branding.ManifestURL = v } if v, ok := brandingData["theme_color"].(string); ok { settings.Branding.ThemeColor = v } if v, ok := brandingData["svg"].(string); ok { settings.Branding.SVG = v } if v, ok := brandingData["favicon_96"].(string); ok { settings.Branding.Favicon96 = v } if v, ok := brandingData["mask_icon"].(string); ok { settings.Branding.MaskIcon = v } if v, ok := brandingData["mstile_150"].(string); ok { settings.Branding.MSTile150 = v } if v, ok := brandingData["browserconfig"].(string); ok { settings.Branding.BrowserConfig = v } } // Admin bypass mode (for showing banner when admin bypasses maintenance/coming_soon) if v, ok := siteData["admin_bypass_mode"].(string); ok { settings.AdminBypassMode = v } // Admin editor toolbar if toolbarData, ok := siteData["toolbar"].(map[string]any); ok { settings.Toolbar = ParseToolbarData(toolbarData) } // AI Optimization settings if aiOpt, ok := siteData["aiOptimization"].(map[string]any); ok { if v, ok := aiOpt["llmsTxtEnabled"].(bool); ok { settings.LLMsTxtEnabled = v } } // RSS feed auto-discovery (injected by page handler from system page) if v, ok := siteData["rss_feed_url"].(string); ok { settings.RSSFeedURL = v } if v, ok := siteData["rss_feed_title"].(string); ok { settings.RSSFeedTitle = v } return settings } // ParsePageMeta extracts page-level SEO metadata from the document map // These fields override site-level defaults when set func ParsePageMeta(doc map[string]any) PageMeta { meta := PageMeta{} // Page-level SEO fields are stored directly in the document root // (matching frontend PageInfo type in web/src/store/editor.ts) if v, ok := doc["metaTitle"].(string); ok { meta.MetaTitle = v } if v, ok := doc["metaDescription"].(string); ok { meta.MetaDescription = v } if v, ok := doc["ogTitle"].(string); ok { meta.OGTitle = v } if v, ok := doc["ogDescription"].(string); ok { meta.OGDescription = v } if v, ok := doc["ogImage"].(string); ok { meta.OGImage = v } if v, ok := doc["twitterTitle"].(string); ok { meta.TwitterTitle = v } if v, ok := doc["twitterDescription"].(string); ok { meta.TwitterDescription = v } if v, ok := doc["twitterImage"].(string); ok { meta.TwitterImage = v } if v, ok := doc["canonicalUrl"].(string); ok { meta.CanonicalURL = v } if v, ok := doc["robotsDirective"].(string); ok { meta.RobotsDirective = v } if v, ok := doc["ogType"].(string); ok { meta.OGType = v } if v, ok := doc["pageUrl"].(string); ok { meta.PageURL = v } if v, ok := doc["articlePublishedTime"].(string); ok { meta.ArticlePublishedTime = v } if v, ok := doc["articleAuthor"].(string); ok { meta.ArticleAuthor = v } return meta } // ParseToolbarData extracts toolbar data from the document map func ParseToolbarData(data map[string]any) ToolbarData { toolbar := ToolbarData{} if v, ok := data["enabled"].(bool); ok { toolbar.Enabled = v } if v, ok := data["page_id"].(string); ok { if id, err := uuid.Parse(v); err == nil { toolbar.PageID = id } } if v, ok := data["page_slug"].(string); ok { toolbar.PageSlug = v } if v, ok := data["page_title"].(string); ok { toolbar.PageTitle = v } if v, ok := data["post_type"].(string); ok { toolbar.PostType = v } if v, ok := data["status"].(string); ok { toolbar.Status = v } if v, ok := data["has_unpublished_changes"].(bool); ok { toolbar.HasUnpublishedChanges = v } if v, ok := data["preview_mode"].(string); ok { toolbar.PreviewMode = v } if v, ok := data["hide_preview_toggle"].(bool); ok { toolbar.HidePreviewToggle = v } if v, ok := data["animate"].(bool); ok { toolbar.Animate = v } if v, ok := data["position"].(string); ok { toolbar.Position = v } if v, ok := data["template_name"].(string); ok { toolbar.TemplateName = v } if v, ok := data["author_name"].(string); ok { toolbar.AuthorName = v } if v, ok := data["author_slug"].(string); ok { toolbar.AuthorSlug = v } if v, ok := data["last_modified"].(time.Time); ok { toolbar.LastModified = v } if v, ok := data["edit_url"].(string); ok { toolbar.EditURL = v } if v, ok := data["settings_url"].(string); ok { toolbar.SettingsURL = v } if v, ok := data["history_url"].(string); ok { toolbar.HistoryURL = v } if v, ok := data["analytics_url"].(string); ok { toolbar.AnalyticsURL = v } // Analytics snapshot if v, ok := data["today_pageviews"].(int64); ok { toolbar.TodayPageviews = v } if v, ok := data["pageviews_trend"].(string); ok { toolbar.PageviewsTrend = v } if v, ok := data["trend_percent"].(int); ok { toolbar.TrendPercent = v } // Blog-specific fields if v, ok := data["reading_time"].(int); ok { toolbar.ReadingTime = v } if v, ok := data["word_count"].(int); ok { toolbar.WordCount = v } if v, ok := data["category_count"].(int); ok { toolbar.CategoryCount = v } return toolbar } // EffectiveTitle returns the title to use in the tag. // Priority: PageMeta.MetaTitle → Page Title | Site Name → Page Title func (d HeadData) EffectiveTitle() string { if d.PageMeta.MetaTitle != "" { return d.PageMeta.MetaTitle } if d.Settings.OGSiteName != "" && d.Title != "" { return d.Title + " | " + d.Settings.OGSiteName } return d.Title } // Head renders the complete <head> element with site settings and plugin extensions. func Head(data HeadData) templ.Component { return templruntime.GeneratedTemplate(func(templ_7745c5c3_Input templruntime.GeneratedComponentInput) (templ_7745c5c3_Err error) { templ_7745c5c3_W, ctx := templ_7745c5c3_Input.Writer, templ_7745c5c3_Input.Context if templ_7745c5c3_CtxErr := ctx.Err(); templ_7745c5c3_CtxErr != nil { return templ_7745c5c3_CtxErr } templ_7745c5c3_Buffer, templ_7745c5c3_IsBuffer := templruntime.GetBuffer(templ_7745c5c3_W) if !templ_7745c5c3_IsBuffer { defer func() { templ_7745c5c3_BufErr := templruntime.ReleaseBuffer(templ_7745c5c3_Buffer) if templ_7745c5c3_Err == nil { templ_7745c5c3_Err = templ_7745c5c3_BufErr } }() } ctx = templ.InitializeContext(ctx) templ_7745c5c3_Var1 := templ.GetChildren(ctx) if templ_7745c5c3_Var1 == nil { templ_7745c5c3_Var1 = templ.NopComponent } ctx = templ.ClearChildren(ctx) templ_7745c5c3_Err = recordValidationCall(ctx, "Head").Render(ctx, templ_7745c5c3_Buffer) if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 1, "<head><meta charset=\"UTF-8\"><meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0\"><title>") if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } var templ_7745c5c3_Var2 string templ_7745c5c3_Var2, templ_7745c5c3_Err = templ.JoinStringErrs(data.EffectiveTitle()) if templ_7745c5c3_Err != nil { return templ.Error{Err: templ_7745c5c3_Err, FileName: `head.templ`, Line: 513, Col: 32} } _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var2)) if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 2, "") if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } if data.CSSHash != "" { templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 3, "") if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } } else { templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 5, "") if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } } templ_7745c5c3_Err = themeInitScript(data.ThemeMode).Render(ctx, templ_7745c5c3_Buffer) if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 6, "") if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } if data.Settings.Branding.IsGenerated { templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 7, " ") if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } if data.Settings.Branding.SVG != "" { templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 8, "") if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } } templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 10, " ") if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } if data.Settings.Branding.Favicon96 != "" { templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 11, "") if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } } templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 13, " ") if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } if data.Settings.Branding.MaskIcon != "" { templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 18, "") if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } } templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 21, " ") if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } if data.Settings.Branding.ThemeColor != "" { templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 23, "") if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } } templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 25, " ") if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } if data.Settings.Branding.BrowserConfig != "" { templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 26, "") if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } } templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 28, " ") if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } if data.Title != "" { templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 29, "") if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } } } else { templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 31, " ") if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } if data.Settings.Favicon != "" { templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 32, "") if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } } templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 34, " ") if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } if data.Settings.AppleTouchIcon != "" { templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 35, "") if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } } } if data.PageMeta.MetaDescription != "" { templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 37, "") if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } } else if data.Settings.MetaDescription != "" { templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 39, "") if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } } if canonical := canonicalURL(data.PageMeta.CanonicalURL, data.PageMeta.PageURL); canonical != "" { templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 41, "") if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } } if data.PageMeta.RobotsDirective != "" { templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 43, "") if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } } if data.Settings.OGSiteName != "" { templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 45, "") if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } } if data.PageMeta.OGTitle != "" { templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 47, "") if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } } else if data.PageMeta.MetaTitle != "" { templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 49, "") if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } } else if data.Title != "" { templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 51, "") if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } } if data.PageMeta.OGDescription != "" { templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 53, "") if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } } else if data.PageMeta.MetaDescription != "" { templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 55, "") if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } } else if data.Settings.MetaDescription != "" { templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 57, "") if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } } if data.PageMeta.OGImage != "" { templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 59, "") if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } } else if data.Settings.DefaultOGImage != "" { templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 61, "") if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } } if data.PageMeta.OGType != "" { templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 63, "") if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } } else { templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 65, "") if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } } if data.PageMeta.PageURL != "" { templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 66, "") if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } } if data.PageMeta.OGType == "article" { if data.PageMeta.ArticlePublishedTime != "" { templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 68, "") if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } } templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 70, " ") if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } if data.PageMeta.ArticleAuthor != "" { templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 71, "") if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } } } if data.Settings.TwitterHandle != "" { templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 73, "") if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } } templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 75, "") if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } if data.PageMeta.TwitterTitle != "" { templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 76, "") if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } } else if data.PageMeta.OGTitle != "" { templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 78, "") if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } } else if data.PageMeta.MetaTitle != "" { templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 80, "") if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } } else if data.Title != "" { templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 82, "") if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } } if data.PageMeta.TwitterDescription != "" { templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 84, "") if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } } else if data.PageMeta.OGDescription != "" { templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 86, "") if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } } else if data.PageMeta.MetaDescription != "" { templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 88, "") if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } } else if data.Settings.MetaDescription != "" { templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 90, "") if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } } if data.PageMeta.TwitterImage != "" { templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 92, "") if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } } else if data.PageMeta.OGImage != "" { templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 94, "") if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } } else if data.Settings.DefaultOGImage != "" { templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 96, "") if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } } if data.Settings.LLMsTxtEnabled { templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 98, "") if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } } if data.Settings.RSSFeedURL != "" { templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 99, "") if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } } if data.Settings.GoogleAnalyticsID != "" && (data.Settings.GoogleAnalyticsEnabled || !data.Settings.GoogleAnalyticsExplicitlySet) { templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 104, " ") if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } templ_7745c5c3_Err = googleAnalyticsScript(data.Settings.GoogleAnalyticsID).Render(ctx, templ_7745c5c3_Buffer) if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } } templ_7745c5c3_Err = analyticsScript(data.PageviewNonce).Render(ctx, templ_7745c5c3_Buffer) if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } templ_7745c5c3_Err = EngagementScript(data.EngagementConfig).Render(ctx, templ_7745c5c3_Buffer) if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } for _, style := range data.PluginStyles { templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 106, "") if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } } if data.ThemeCSS != "" { templ_7745c5c3_Err = themeStyle(data.ThemeCSS).Render(ctx, templ_7745c5c3_Buffer) if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } } for _, script := range data.Settings.CustomScripts { if script.Enabled && script.Placement == "head" { templ_7745c5c3_Err = templ.Raw(script.Code).Render(ctx, templ_7745c5c3_Buffer) if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } } } if data.StructuredData != "" { templ_7745c5c3_Err = structuredDataScript(data.StructuredData).Render(ctx, templ_7745c5c3_Buffer) if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } } templ_7745c5c3_Err = templ_7745c5c3_Var1.Render(ctx, templ_7745c5c3_Buffer) if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 108, "") if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } return nil }) } // structuredDataScript renders JSON-LD structured data func structuredDataScript(jsonLD string) templ.Component { return templ.Raw(``) } // AdminBypassBanner renders a banner when admin is bypassing maintenance/coming_soon mode // This should be rendered at the very start of the to push down all content func AdminBypassBanner(settings SiteSettingsData) templ.Component { return templruntime.GeneratedTemplate(func(templ_7745c5c3_Input templruntime.GeneratedComponentInput) (templ_7745c5c3_Err error) { templ_7745c5c3_W, ctx := templ_7745c5c3_Input.Writer, templ_7745c5c3_Input.Context if templ_7745c5c3_CtxErr := ctx.Err(); templ_7745c5c3_CtxErr != nil { return templ_7745c5c3_CtxErr } templ_7745c5c3_Buffer, templ_7745c5c3_IsBuffer := templruntime.GetBuffer(templ_7745c5c3_W) if !templ_7745c5c3_IsBuffer { defer func() { templ_7745c5c3_BufErr := templruntime.ReleaseBuffer(templ_7745c5c3_Buffer) if templ_7745c5c3_Err == nil { templ_7745c5c3_Err = templ_7745c5c3_BufErr } }() } ctx = templ.InitializeContext(ctx) templ_7745c5c3_Var53 := templ.GetChildren(ctx) if templ_7745c5c3_Var53 == nil { templ_7745c5c3_Var53 = templ.NopComponent } ctx = templ.ClearChildren(ctx) if settings.AdminBypassMode != "" { templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 109, "
") if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } if settings.AdminBypassMode == "maintenance" { templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 110, "Maintenance Mode Active — You're seeing the normal site because you're logged in as admin. Manage") if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } } else if settings.AdminBypassMode == "coming_soon" { templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 111, "Coming Soon Mode Active — You're seeing the normal site because you're logged in as admin. Manage") if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } } templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 112, "
") if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } } return nil }) } // BodyEnd renders custom scripts and admin toolbar before func BodyEnd(settings SiteSettingsData) templ.Component { return templruntime.GeneratedTemplate(func(templ_7745c5c3_Input templruntime.GeneratedComponentInput) (templ_7745c5c3_Err error) { templ_7745c5c3_W, ctx := templ_7745c5c3_Input.Writer, templ_7745c5c3_Input.Context if templ_7745c5c3_CtxErr := ctx.Err(); templ_7745c5c3_CtxErr != nil { return templ_7745c5c3_CtxErr } templ_7745c5c3_Buffer, templ_7745c5c3_IsBuffer := templruntime.GetBuffer(templ_7745c5c3_W) if !templ_7745c5c3_IsBuffer { defer func() { templ_7745c5c3_BufErr := templruntime.ReleaseBuffer(templ_7745c5c3_Buffer) if templ_7745c5c3_Err == nil { templ_7745c5c3_Err = templ_7745c5c3_BufErr } }() } ctx = templ.InitializeContext(ctx) templ_7745c5c3_Var54 := templ.GetChildren(ctx) if templ_7745c5c3_Var54 == nil { templ_7745c5c3_Var54 = templ.NopComponent } ctx = templ.ClearChildren(ctx) templ_7745c5c3_Err = recordValidationCall(ctx, "BodyEnd").Render(ctx, templ_7745c5c3_Buffer) if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } for _, script := range settings.CustomScripts { if script.Enabled && script.Placement == "body" { templ_7745c5c3_Err = templ.Raw(script.Code).Render(ctx, templ_7745c5c3_Buffer) if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } } } templ_7745c5c3_Err = AdminEditorToolbar(settings.Toolbar).Render(ctx, templ_7745c5c3_Buffer) if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } templ_7745c5c3_Err = templ_7745c5c3_Var54.Render(ctx, templ_7745c5c3_Buffer) if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } return nil }) } // themeStyle renders the theme CSS variables func themeStyleComponent(css string) templ.Component { return templ.Raw(``) } func themeStyle(css string) templ.Component { return templruntime.GeneratedTemplate(func(templ_7745c5c3_Input templruntime.GeneratedComponentInput) (templ_7745c5c3_Err error) { templ_7745c5c3_W, ctx := templ_7745c5c3_Input.Writer, templ_7745c5c3_Input.Context if templ_7745c5c3_CtxErr := ctx.Err(); templ_7745c5c3_CtxErr != nil { return templ_7745c5c3_CtxErr } templ_7745c5c3_Buffer, templ_7745c5c3_IsBuffer := templruntime.GetBuffer(templ_7745c5c3_W) if !templ_7745c5c3_IsBuffer { defer func() { templ_7745c5c3_BufErr := templruntime.ReleaseBuffer(templ_7745c5c3_Buffer) if templ_7745c5c3_Err == nil { templ_7745c5c3_Err = templ_7745c5c3_BufErr } }() } ctx = templ.InitializeContext(ctx) templ_7745c5c3_Var55 := templ.GetChildren(ctx) if templ_7745c5c3_Var55 == nil { templ_7745c5c3_Var55 = templ.NopComponent } ctx = templ.ClearChildren(ctx) templ_7745c5c3_Err = themeStyleComponent(css).Render(ctx, templ_7745c5c3_Buffer) if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } return nil }) } // googleAnalyticsScript renders the GA4 inline script func googleAnalyticsScript(gaID string) templ.Component { return templ.Raw(``) } // analyticsScript renders the built-in analytics tracking script (cookie-less) // nonce is used for deduplication with server-side tracking func analyticsScript(nonce string) templ.Component { return templruntime.GeneratedTemplate(func(templ_7745c5c3_Input templruntime.GeneratedComponentInput) (templ_7745c5c3_Err error) { templ_7745c5c3_W, ctx := templ_7745c5c3_Input.Writer, templ_7745c5c3_Input.Context if templ_7745c5c3_CtxErr := ctx.Err(); templ_7745c5c3_CtxErr != nil { return templ_7745c5c3_CtxErr } templ_7745c5c3_Buffer, templ_7745c5c3_IsBuffer := templruntime.GetBuffer(templ_7745c5c3_W) if !templ_7745c5c3_IsBuffer { defer func() { templ_7745c5c3_BufErr := templruntime.ReleaseBuffer(templ_7745c5c3_Buffer) if templ_7745c5c3_Err == nil { templ_7745c5c3_Err = templ_7745c5c3_BufErr } }() } ctx = templ.InitializeContext(ctx) templ_7745c5c3_Var56 := templ.GetChildren(ctx) if templ_7745c5c3_Var56 == nil { templ_7745c5c3_Var56 = templ.NopComponent } ctx = templ.ClearChildren(ctx) templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 113, "") if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } return nil }) } func themeInitScript(themeMode string) templ.Component { switch themeMode { case "light", "dark", "system": default: themeMode = "light" } // Precedence: admin toolbar override (per-tab, sessionStorage) → visitor // preference (bn-theme cookie/localStorage) → site default → system. // Exposed as window.bnApplyTheme so the toolbar theme tester can re-apply // after changing the override without duplicating this resolution. return templ.Raw(``) } var _ = templruntime.GeneratedTemplate