All checks were successful
Build and Release / Create Release (push) Successful in 0s
Build and Release / Unit Tests (push) Successful in 3m20s
Build and Release / Integration Tests (PostgreSQL) (push) Successful in 4m41s
Build and Release / Lint (push) Successful in 4m56s
Build and Release / Build Binaries (amd64, linux, linux-latest) (push) Successful in 2m49s
Build and Release / Build Binaries (amd64, windows, windows-latest) (push) Successful in 9h4m28s
Build and Release / Build Binaries (arm64, darwin, macos) (push) Successful in 6m39s
Build and Release / Build Binaries (amd64, darwin, macos) (push) Successful in 8m53s
Build and Release / Build Binary (linux/arm64) (push) Successful in 8m25s
Adds standalone blog post view at /blog/:id with full content rendering, comments, reactions, and OpenGraph metadata. Implements optional "Blogs" link in site header navigation (configurable in admin settings). Enforces repository access permissions on standalone view. Loads repo owners for avatar fallback on explore page. Includes SEO-friendly URLs and social media sharing support.
138 lines
4.9 KiB
Go
138 lines
4.9 KiB
Go
// Copyright 2023 The Gitea Authors. All rights reserved.
|
|
// SPDX-License-Identifier: MIT
|
|
|
|
package setting
|
|
|
|
import (
|
|
"strings"
|
|
"sync"
|
|
|
|
"code.gitcaddy.com/server/v3/modules/log"
|
|
"code.gitcaddy.com/server/v3/modules/setting/config"
|
|
)
|
|
|
|
type PictureStruct struct {
|
|
DisableGravatar *config.Value[bool]
|
|
EnableFederatedAvatar *config.Value[bool]
|
|
}
|
|
|
|
type OpenWithEditorApp struct {
|
|
DisplayName string
|
|
OpenURL string
|
|
}
|
|
|
|
type OpenWithEditorAppsType []OpenWithEditorApp
|
|
|
|
func (t OpenWithEditorAppsType) ToTextareaString() string {
|
|
var ret strings.Builder
|
|
for _, app := range t {
|
|
ret.WriteString(app.DisplayName + " = " + app.OpenURL + "\n")
|
|
}
|
|
return ret.String()
|
|
}
|
|
|
|
func DefaultOpenWithEditorApps() OpenWithEditorAppsType {
|
|
return OpenWithEditorAppsType{
|
|
{
|
|
DisplayName: "VS Code",
|
|
OpenURL: "vscode://vscode.git/clone?url={url}",
|
|
},
|
|
{
|
|
DisplayName: "VSCodium",
|
|
OpenURL: "vscodium://vscode.git/clone?url={url}",
|
|
},
|
|
{
|
|
DisplayName: "Intellij IDEA",
|
|
OpenURL: "jetbrains://idea/checkout/git?idea.required.plugins.id=Git4Idea&checkout.repo={url}",
|
|
},
|
|
}
|
|
}
|
|
|
|
type RepositoryStruct struct {
|
|
OpenWithEditorApps *config.Value[OpenWithEditorAppsType]
|
|
GitGuideRemoteName *config.Value[string]
|
|
}
|
|
|
|
type ThemeStruct struct {
|
|
DisableRegistration *config.Value[bool]
|
|
HideExploreUsers *config.Value[bool]
|
|
HideExploreButton *config.Value[bool]
|
|
EnableExplorePackages *config.Value[bool]
|
|
HelpURL *config.Value[string]
|
|
CustomSiteIconURL *config.Value[string]
|
|
CustomHomeLogoURL *config.Value[string]
|
|
CustomHomeHTML *config.Value[string]
|
|
APIHeaderURL *config.Value[string]
|
|
CustomHomeTitle *config.Value[string]
|
|
CustomHomeTagline *config.Value[string]
|
|
PinnedOrgDisplayFormat *config.Value[string]
|
|
ExploreOrgDisplayFormat *config.Value[string]
|
|
EnableBlogs *config.Value[bool]
|
|
BlogsInTopNav *config.Value[bool]
|
|
}
|
|
|
|
type ConfigStruct struct {
|
|
Picture *PictureStruct
|
|
Repository *RepositoryStruct
|
|
Theme *ThemeStruct
|
|
}
|
|
|
|
var (
|
|
defaultConfig *ConfigStruct
|
|
defaultConfigOnce sync.Once
|
|
)
|
|
|
|
func initDefaultConfig() {
|
|
config.SetCfgSecKeyGetter(&cfgSecKeyGetter{})
|
|
defaultConfig = &ConfigStruct{
|
|
Picture: &PictureStruct{
|
|
DisableGravatar: config.ValueJSON[bool]("picture.disable_gravatar").WithFileConfig(config.CfgSecKey{Sec: "picture", Key: "DISABLE_GRAVATAR"}),
|
|
EnableFederatedAvatar: config.ValueJSON[bool]("picture.enable_federated_avatar").WithFileConfig(config.CfgSecKey{Sec: "picture", Key: "ENABLE_FEDERATED_AVATAR"}),
|
|
},
|
|
Repository: &RepositoryStruct{
|
|
OpenWithEditorApps: config.ValueJSON[OpenWithEditorAppsType]("repository.open-with.editor-apps"),
|
|
GitGuideRemoteName: config.ValueJSON[string]("repository.git-guide-remote-name").WithDefault("origin"),
|
|
},
|
|
Theme: &ThemeStruct{
|
|
DisableRegistration: config.ValueJSON[bool]("theme.disable_registration").WithFileConfig(config.CfgSecKey{Sec: "service", Key: "DISABLE_REGISTRATION"}),
|
|
HideExploreUsers: config.ValueJSON[bool]("theme.hide_explore_users").WithDefault(false),
|
|
HideExploreButton: config.ValueJSON[bool]("theme.hide_explore_button").WithDefault(false),
|
|
EnableExplorePackages: config.ValueJSON[bool]("theme.enable_explore_packages").WithFileConfig(config.CfgSecKey{Sec: "service.explore", Key: "ENABLE_PACKAGES_PAGE"}),
|
|
HelpURL: config.ValueJSON[string]("theme.help_url").WithDefault(""),
|
|
CustomSiteIconURL: config.ValueJSON[string]("theme.custom_site_icon_url").WithDefault(""),
|
|
CustomHomeLogoURL: config.ValueJSON[string]("theme.custom_home_logo_url").WithDefault(""),
|
|
CustomHomeHTML: config.ValueJSON[string]("theme.custom_home_html").WithDefault(""),
|
|
APIHeaderURL: config.ValueJSON[string]("theme.api_header_url").WithDefault(""),
|
|
CustomHomeTitle: config.ValueJSON[string]("theme.custom_home_title").WithDefault(""),
|
|
CustomHomeTagline: config.ValueJSON[string]("theme.custom_home_tagline").WithDefault(""),
|
|
PinnedOrgDisplayFormat: config.ValueJSON[string]("theme.pinned_org_display_format").WithDefault("condensed"),
|
|
ExploreOrgDisplayFormat: config.ValueJSON[string]("theme.explore_org_display_format").WithDefault("list"),
|
|
EnableBlogs: config.ValueJSON[bool]("theme.enable_blogs").WithDefault(false),
|
|
BlogsInTopNav: config.ValueJSON[bool]("theme.blogs_in_top_nav").WithDefault(false),
|
|
},
|
|
}
|
|
}
|
|
|
|
func Config() *ConfigStruct {
|
|
defaultConfigOnce.Do(initDefaultConfig)
|
|
return defaultConfig
|
|
}
|
|
|
|
type cfgSecKeyGetter struct{}
|
|
|
|
func (c cfgSecKeyGetter) GetValue(sec, key string) (v string, has bool) {
|
|
if key == "" {
|
|
return "", false
|
|
}
|
|
cfgSec, err := CfgProvider.GetSection(sec)
|
|
if err != nil {
|
|
log.Error("Unable to get config section: %q", sec)
|
|
return "", false
|
|
}
|
|
cfgKey := ConfigSectionKey(cfgSec, key)
|
|
if cfgKey == nil {
|
|
return "", false
|
|
}
|
|
return cfgKey.Value(), true
|
|
}
|