Documentation
¶
Overview ¶
Package theme 提供主题管理功能:解析 theme.yaml、管理主题生命周期。
Index ¶
- Constants
- Variables
- func HasLegacyWidgetConfig(userConfigJSON string) bool
- func IsBuiltinWidget(id string) bool
- func MarshalMenuConfig(items []MenuConfigItem) (string, error)
- func MenuPageID(id uint) string
- func MenuSettingKey(location string) string
- func MissingWidgets(userConfigJSON string, t *Theme) []string
- func OptionKey(themeName, optionID string) string
- func RegisterBuiltins(r *hook.WidgetRegistry)
- func RegisterThemeWidgets(widgetRegistry *hook.WidgetRegistry, t *Theme)
- type API
- type FunctionsScript
- type Manager
- func (m *Manager) Activate(ctx context.Context, name string) error
- func (m *Manager) BindTemplateFunctions()
- func (m *Manager) ClearPreviewTheme()
- func (m *Manager) ClearRecoveryInfo()
- func (m *Manager) Current(ctx context.Context) *Theme
- func (m *Manager) CurrentScript() *FunctionsScript
- func (m *Manager) CurrentWithPreview(ctx context.Context, previewName string) *Theme
- func (m *Manager) Delete(name string) error
- func (m *Manager) Get(name string) *Theme
- func (m *Manager) GetRecoveryInfo() *RecoveryInfo
- func (m *Manager) Install(dir string) (*Theme, error)
- func (m *Manager) List() []*Theme
- func (m *Manager) ListThemeFiles(name string) ([]ThemeFile, error)
- func (m *Manager) LoadPreviewTheme(name string) error
- func (m *Manager) LoadTheme(ctx context.Context, name string) error
- func (m *Manager) LoadTranslations() error
- func (m *Manager) RebuildTranslations() error
- func (m *Manager) ReloadCurrentTheme(ctx context.Context) error
- func (m *Manager) SetHookRegistry(reg hook.Registry)
- func (m *Manager) SetLogger(log *slog.Logger)
- func (m *Manager) SetPluginWidgetsProvider(provider hook.WidgetDeclProvider)
- func (m *Manager) ThemeDir(name string) string
- func (m *Manager) ThemeFilePath(name, relPath string) (string, error)
- func (m *Manager) ThemesDir() string
- func (m *Manager) WidgetDecls(ctx context.Context, t *Theme, area string) []WidgetDecl
- type MenuConfigItem
- type MenuItem
- type MenuLocation
- type MenuLocationEntries
- type MenuLocationEntry
- type OptionDecl
- type RecoveryInfo
- type SelectOpt
- type TemplateWidget
- type Theme
- func (t *Theme) AssetsDir() string
- func (t *Theme) HasAssets() bool
- func (t *Theme) HasTemplates() bool
- func (t *Theme) I18nDir() string
- func (t *Theme) LoadTranslations() error
- func (t *Theme) ScreenshotURL() string
- func (t *Theme) TemplatesDir() string
- func (t *Theme) ThemeDomain() string
- func (t *Theme) WidgetsDir() string
- type ThemeFile
- type WidgetArea
- type WidgetConfigItem
- type WidgetDecl
- type WidgetInfo
Constants ¶
const ( // WidgetSourceBuiltin 表示内置组件。 WidgetSourceBuiltin = "builtin" // WidgetSourceTheme 表示主题提供的组件。 WidgetSourceTheme = "theme" // WidgetSourcePlugin 表示插件提供的组件。 WidgetSourcePlugin = "plugin" )
const MenuItemTypeCustom = "custom"
const MenuItemTypePage = "page"
Variables ¶
var BuiltinWidgetDecls = []WidgetDecl{ {ID: "user_info", Label: gettext.Mark.T("用户信息"), Options: []OptionDecl{ {ID: "title", Type: "text", Label: gettext.Mark.T("标题"), Description: gettext.Mark.T("留空时根据登录状态显示欢迎语")}, }}, {ID: "search", Label: gettext.Mark.T("搜索"), Options: []OptionDecl{ {ID: "title", Type: "text", Label: gettext.Mark.T("标题"), Default: gettext.Mark.T("搜索")}, }}, {ID: "recent_posts", Label: gettext.Mark.T("近期文章"), Options: []OptionDecl{ {ID: "title", Type: "text", Label: gettext.Mark.T("标题"), Default: gettext.Mark.T("近期文章")}, {ID: "count", Type: "number", Label: gettext.Mark.T("显示数量"), Default: "5", Min: floatPtr(1), Max: floatPtr(20)}, }}, {ID: "recent_comments", Label: gettext.Mark.T("近期评论"), Options: []OptionDecl{ {ID: "title", Type: "text", Label: gettext.Mark.T("标题"), Default: gettext.Mark.T("近期评论")}, {ID: "count", Type: "number", Label: gettext.Mark.T("显示数量"), Default: "5", Min: floatPtr(1), Max: floatPtr(20)}, }}, {ID: "categories", Label: gettext.Mark.T("分类目录"), Options: []OptionDecl{ {ID: "title", Type: "text", Label: gettext.Mark.T("标题"), Default: gettext.Mark.T("分类目录")}, }}, {ID: "tag_cloud", Label: gettext.Mark.T("标签云"), Options: []OptionDecl{ {ID: "title", Type: "text", Label: gettext.Mark.T("标题"), Default: gettext.Mark.T("标签")}, }}, {ID: "archive_months", Label: gettext.Mark.T("归档"), Options: []OptionDecl{ {ID: "title", Type: "text", Label: gettext.Mark.T("标题"), Default: gettext.Mark.T("归档")}, }}, {ID: "custom_html", Label: gettext.Mark.T("自定义 HTML"), Options: []OptionDecl{ {ID: "title", Type: "text", Label: gettext.Mark.T("标题")}, {ID: "html", Type: "textarea", Label: gettext.Mark.T("HTML 内容"), Description: gettext.Mark.T("任意 HTML 代码,会原样输出到页面中")}, }}, }
BuiltinWidgetDecls 内置组件声明。主题只需要声明组件区域即可使用这些组件; 若主题在 theme.yaml 中声明了同 ID 组件,则以主题声明为准。
var BuiltinWidgetIDs = []string{"user_info", "search", "recent_posts", "recent_comments", "categories", "tag_cloud", "archive_months", "custom_html"}
BuiltinWidgetIDs 内置组件 ID 列表。
Functions ¶
func HasLegacyWidgetConfig ¶
HasLegacyWidgetConfig 判断配置中是否存在缺少 source 的旧格式条目。 插件化后组件 ID 不再全局唯一,旧格式无法可靠判断来源,因此需要清空后重新配置。
func MarshalMenuConfig ¶
func MarshalMenuConfig(items []MenuConfigItem) (string, error)
func MenuPageID ¶
func MenuSettingKey ¶
func MissingWidgets ¶
MissingWidgets 返回用户配置中存在但当前主题未声明的组件 ID 列表。
func RegisterBuiltins ¶
func RegisterBuiltins(r *hook.WidgetRegistry)
RegisterBuiltins 注册所有内置组件到注册表。
func RegisterThemeWidgets ¶
func RegisterThemeWidgets(widgetRegistry *hook.WidgetRegistry, t *Theme)
RegisterThemeWidgets 注册主题声明的组件到注册表。
Types ¶
type API ¶
API 是 hook.API 在 internal/theme 中的包装,负责桥接内部主题声明类型。
func NewAPI ¶
func NewAPI(domain string, loader *store.DataLoader, opts []OptionDecl) *API
NewAPI 创建主题 Hook API 实例。
type FunctionsScript ¶
type FunctionsScript struct {
// contains filtered or unexported fields
}
FunctionsScript 表示一个已编译的 functions.go 脚本。
func CompileFunctions ¶
func CompileFunctions(ctx context.Context, themeDir string, api *API, log *slog.Logger) (*FunctionsScript, error)
CompileFunctions 编译主题目录下的 functions.go 或 functions.goyaegi 文件。 返回编译后的脚本实例;如果文件不存在则返回 nil, nil。
type Manager ¶
type Manager struct {
// contains filtered or unexported fields
}
Manager 管理主题的安装、激活、删除。
func NewManager ¶
func NewManager(themesDir string, store hook.SettingStore, renderer *render.Renderer) (*Manager, error)
NewManager 创建主题管理器。themesDir 是主题存放目录(如 "themes")。
func (*Manager) BindTemplateFunctions ¶
func (m *Manager) BindTemplateFunctions()
BindTemplateFunctions 把主题运行时能力绑定到模板函数。
主题模板中的函数调用统一走这条链路:
模板函数 → render.RequestContext → theme.Manager → store/主题声明。
这样 cmd/server 只负责组装依赖,不再了解 widget/option 的 Setting key 细节。
func (*Manager) ClearPreviewTheme ¶
func (m *Manager) ClearPreviewTheme()
ClearPreviewTheme 清除 Renderer 中的预览主题模板缓存。
func (*Manager) ClearRecoveryInfo ¶
func (m *Manager) ClearRecoveryInfo()
ClearRecoveryInfo 清除恢复信息(管理员确认后调用)。
func (*Manager) CurrentScript ¶
func (m *Manager) CurrentScript() *FunctionsScript
CurrentScript 返回当前激活的 functions.go 脚本,nil 表示无脚本。
func (*Manager) CurrentWithPreview ¶
CurrentWithPreview 返回预览主题(如果 previewName 有效),否则返回当前激活主题。 previewName 为空时等同于 Current()。
func (*Manager) GetRecoveryInfo ¶
func (m *Manager) GetRecoveryInfo() *RecoveryInfo
RecoveryInfo 返回最近一次主题加载失败的恢复信息,nil 表示一切正常。
func (*Manager) Install ¶
Install 从已解压的目录安装主题。dir 是主题根目录(含 theme.yaml)。 安装过程:校验 → 暂存复制 → 备份旧目录 → 原子替换。
func (*Manager) ListThemeFiles ¶
ListThemeFiles 列出主题目录下的所有可编辑文件。
func (*Manager) LoadPreviewTheme ¶
LoadPreviewTheme 加载预览主题的模板到 Renderer 的独立缓存,不影响主模板。
func (*Manager) LoadTheme ¶
LoadTheme 加载指定主题:模板 + functions.go。 任一步骤失败则自动回退到默认主题。 name 为空时加载当前激活的主题。 返回 nil 表示加载成功;返回 error 表示已回退到默认主题。
func (*Manager) LoadTranslations ¶
LoadTranslations 加载所有已安装主题自带的翻译文件。
func (*Manager) RebuildTranslations ¶
RebuildTranslations 重新构建应用域和所有主题域的翻译映射。 适用于主题安装/删除后清理失效 domain,同时保留当前 locale 配置。
func (*Manager) ReloadCurrentTheme ¶
ReloadCurrentTheme 重新加载当前激活的主题(文件编辑器保存后调用)。
func (*Manager) SetHookRegistry ¶
SetHookRegistry 设置共享 Hook Registry(启动时调用一次,之后只读)。
func (*Manager) SetPluginWidgetsProvider ¶
func (m *Manager) SetPluginWidgetsProvider(provider hook.WidgetDeclProvider)
SetPluginWidgetsProvider 设置插件小组件声明提供者(启动时调用一次,之后只读)。
func (*Manager) ThemeFilePath ¶
ThemeFilePath 校验并返回主题文件的安全路径。 防止路径穿越攻击。
func (*Manager) WidgetDecls ¶
WidgetDecls 返回当前主题可用组件声明,并追加当前启用插件声明的小组件。
type MenuConfigItem ¶
type MenuConfigItem struct {
ID string `json:"id"`
Type string `json:"type"`
PostID uint `json:"post_id,omitempty"`
Title string `json:"title,omitempty"`
URL string `json:"url,omitempty"`
ParentID string `json:"parent_id,omitempty"`
Target string `json:"target,omitempty"`
Order int `json:"order,omitempty"`
}
MenuConfigItem 是后台保存的菜单配置项,采用扁平结构便于表单编辑。
func ParseMenuConfig ¶
func ParseMenuConfig(raw string) []MenuConfigItem
type MenuItem ¶
MenuItem 是模板渲染用的菜单树节点。
func BuildMenuTree ¶
func BuildMenuTree(config []MenuConfigItem, pages map[uint]model.Post) []MenuItem
func MenuItemsFromPages ¶
type MenuLocation ¶
type MenuLocation struct {
Name string `yaml:"name" json:"name"`
Description string `yaml:"description" json:"description"`
}
MenuLocation 描述一个主题菜单位置。
type MenuLocationEntries ¶
type MenuLocationEntries []MenuLocationEntry
MenuLocationEntries 是有序的菜单位置列表,UnmarshalYAML 保留 YAML mapping 的 key 顺序。
func (*MenuLocationEntries) UnmarshalYAML ¶
func (e *MenuLocationEntries) UnmarshalYAML(value *yaml.Node) error
type MenuLocationEntry ¶
type MenuLocationEntry struct {
Key string
MenuLocation
}
MenuLocationEntry 是带 key 的菜单位置条目,用于保留主题声明的顺序。
type RecoveryInfo ¶
RecoveryInfo 记录主题加载失败时的恢复信息。
type TemplateWidget ¶
type TemplateWidget struct {
// contains filtered or unexported fields
}
TemplateWidget 是基于模板渲染的组件适配器,内置组件和主题组件使用此实现。
func NewTemplateWidget ¶
func NewTemplateWidget(decl hook.WidgetDecl) *TemplateWidget
NewTemplateWidget 创建模板型组件。
func (*TemplateWidget) Meta ¶
func (w *TemplateWidget) Meta() hook.WidgetDecl
type Theme ¶
type Theme struct {
Name string `yaml:"name" json:"name"`
Version string `yaml:"version" json:"version"`
Description string `yaml:"description" json:"description"`
Author string `yaml:"author" json:"author"`
// Screenshot 是主题目录内的截图文件名(如 screenshot.png),为空表示无截图。
Screenshot string `yaml:"screenshot" json:"screenshot"`
// ThemeURI 是主题主页 URL。
ThemeURI string `yaml:"theme_uri" json:"theme_uri"`
// AuthorURI 是作者主页 URL。
AuthorURI string `yaml:"author_uri" json:"author_uri"`
// License 是许可证名称(如 MIT、GPL-2.0)。
License string `yaml:"license" json:"license"`
// LicenseURI 是许可证全文 URL。
LicenseURI string `yaml:"license_uri" json:"license_uri"`
// Tags 是主题标签列表。
Tags []string `yaml:"tags" json:"tags"`
// Dir 是主题在磁盘上的根目录(如 themes/default),由 Manager 填充。
Dir string `yaml:"-" json:"-"`
// WidgetAreas 是主题声明的组件区域。
WidgetAreas map[string]WidgetArea `yaml:"widget_areas" json:"widget_areas"`
// MenuLocations 是主题声明的菜单位置,如 primary/footer,顺序与 theme.yaml 声明一致。
MenuLocations MenuLocationEntries `yaml:"menu_locations" json:"menu_locations"`
// Widgets 是主题声明的可用组件列表。
Widgets []WidgetDecl `yaml:"widgets" json:"widgets"`
// Options 是主题声明的全局可配置选项。
Options []hook.OptionDecl `yaml:"options" json:"options"`
// WidgetTemplates 是主题 widgets/ 目录中实际存在的组件模板 ID 集合。
WidgetTemplates map[string]bool `yaml:"-" json:"-"`
}
Theme 表示一个已安装的主题。
func (*Theme) LoadTranslations ¶
LoadTranslations 把主题 i18n 目录绑定到主题名称对应的文本域。
func (*Theme) ScreenshotURL ¶
ScreenshotURL 返回主题截图的访问 URL,无截图时返回空字符串。
func (*Theme) ThemeDomain ¶
ThemeDomain 返回主题翻译使用的文本域名(加 theme_ 前缀避免与应用默认域冲突)。
type WidgetArea ¶
type WidgetArea struct {
Name string `yaml:"name" json:"name"`
Description string `yaml:"description" json:"description"`
}
WidgetArea 描述一个可配置的组件区域。
type WidgetConfigItem ¶
type WidgetConfigItem struct {
InstanceID string `json:"instance_id,omitempty"`
ID string `json:"id"`
Source string `json:"source,omitempty"`
Opts map[string]string `json:"opts,omitempty"`
}
WidgetConfigItem 是组件配置对象数组中的一个条目。
func ParseWidgetConfig ¶
func ParseWidgetConfig(userConfigJSON string) []WidgetConfigItem
ParseWidgetConfig 解析用户配置 JSON。
type WidgetDecl ¶
type WidgetDecl = hook.WidgetDecl
WidgetDecl 是 hook.WidgetDecl 的别名,描述主题声明的一个可用组件。
func WidgetDeclsWithBuiltins ¶
func WidgetDeclsWithBuiltins(t *Theme) []WidgetDecl
WidgetDeclsWithBuiltins 返回主题组件声明与内置组件声明的合并结果。
func WidgetDeclsWithPlugins ¶
func WidgetDeclsWithPlugins(t *Theme, pluginWidgets []WidgetDecl) []WidgetDecl
WidgetDeclsWithPlugins 返回主题、内置和当前启用插件的组件声明列表。
type WidgetInfo ¶
type WidgetInfo = render.WidgetInfo
WidgetInfo 渲染时使用的组件信息。
func ResolveWidgetsWithDecls ¶
func ResolveWidgetsWithDecls(ctx context.Context, userConfigJSON string, t *Theme, area string, decls []WidgetDecl) []WidgetInfo
ResolveWidgetsWithDecls 根据用户配置和已过滤的组件声明解析区域组件列表。