fix: 拆除爬虫专用 HTML,并补齐 /favicon.ico 与 head 图标注入
人机统一走 SPA/首页 SSR;约定路径与 link rel=icon 便于爬虫识别站点图标。 Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
@@ -14,9 +14,10 @@ import (
|
||||
var staticFS embed.FS
|
||||
|
||||
var (
|
||||
spaTitleRe = regexp.MustCompile(`(?s)<title>.*?</title>`)
|
||||
spaBrandTitleFn func() string
|
||||
spaBrandJSONFn func() []byte // 站点品牌 JSON,注入 window.__J13_BRANDING__
|
||||
spaTitleRe = regexp.MustCompile(`(?s)<title>.*?</title>`)
|
||||
spaBrandTitleFn func() string
|
||||
spaBrandJSONFn func() []byte // 站点品牌 JSON,注入 window.__J13_BRANDING__
|
||||
spaBrandFaviconFn func() string // 站点 Favicon URL,注入 <link rel="icon">
|
||||
)
|
||||
|
||||
// SetSPADocumentTitle 注册站点标题提供者,ServeSPA 会注入到入口 HTML,避免刷新闪烁
|
||||
@@ -29,6 +30,11 @@ func SetSPABrandingJSON(fn func() []byte) {
|
||||
spaBrandJSONFn = fn
|
||||
}
|
||||
|
||||
// SetSPAFaviconURL 注册 Favicon URL 提供者,注入到入口 HTML 的 <link rel="icon">
|
||||
func SetSPAFaviconURL(fn func() string) {
|
||||
spaBrandFaviconFn = fn
|
||||
}
|
||||
|
||||
// SetupEmbed 配置内嵌资源:React SPA 静态资源
|
||||
func SetupEmbed(r *gin.Engine) error {
|
||||
if sub, err := fs.Sub(staticFS, "static/spa/assets"); err == nil {
|
||||
|
||||
@@ -62,13 +62,17 @@ func applySPAPageMeta(data []byte, meta *SPAPageMeta) []byte {
|
||||
data = spaTitleRe.ReplaceAll(data, []byte("<title>"+escaped+"</title>"))
|
||||
}
|
||||
|
||||
// —— 静态 SEO HTML(meta / OG / JSON-LD),紧跟 </title>,不经 JS ——
|
||||
// —— 静态 SEO HTML(meta / OG / JSON-LD / favicon),紧跟 </title>,不经 JS ——
|
||||
var seo strings.Builder
|
||||
writeMeta(&seo, "description", meta.Description)
|
||||
writeMeta(&seo, "keywords", meta.Keywords)
|
||||
if canonical := strings.TrimSpace(meta.Canonical); canonical != "" {
|
||||
seo.WriteString(`<link rel="canonical" href="` + html.EscapeString(canonical) + `"/>`)
|
||||
}
|
||||
if favicon := spaFaviconHref(); favicon != "" {
|
||||
seo.WriteString(`<link rel="icon" href="` + html.EscapeString(favicon) + `"/>`)
|
||||
seo.WriteString(`<link rel="shortcut icon" href="` + html.EscapeString(favicon) + `"/>`)
|
||||
}
|
||||
robots := strings.TrimSpace(meta.Robots)
|
||||
if robots != "" {
|
||||
writeMeta(&seo, "robots", robots)
|
||||
@@ -187,3 +191,11 @@ func firstNonEmpty(vals ...string) string {
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
// spaFaviconHref 当前站点配置的 Favicon(相对或绝对 URL)
|
||||
func spaFaviconHref() string {
|
||||
if spaBrandFaviconFn == nil {
|
||||
return ""
|
||||
}
|
||||
return strings.TrimSpace(spaBrandFaviconFn())
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user