feat: links settings and outbound rules in resolve

- migration 202610280003: settings links_new_tab (default on),
  nofollow_domains and sponsored_domains; robots llms_enabled and
  llms_intro (used by the llms.txt commit)
- SEO settings Links tab: the new-tab switch and the two domain lists,
  one domain per line, lowercased, refused with settings.domain_invalid
  naming the line; writable through seo_update_settings
- the resolve answer of an ok page carries outbound {new_tab,
  nofollow_domains, sponsored_domains}; no existing key changes
This commit is contained in:
Jakub Zych
2026-11-04 13:26:31 +01:00
parent 26193ae4eb
commit 49d3879954
11 changed files with 283 additions and 12 deletions

View File

@@ -37,7 +37,8 @@ var SettingsColumns = []string{
"site_name", "twitter_site", "title_template", "home_template",
"default_description", "default_og_image", "query_params",
"noindex_paths", "search_paths", "url_host", "url_slash",
"url_lowercase", "verify_google", "verify_bing", "verify_yandex",
"url_lowercase", "links_new_tab", "nofollow_domains",
"sponsored_domains", "verify_google", "verify_bing", "verify_yandex",
"verify_other", "verify_files", "csv_delimiter",
}
@@ -57,6 +58,9 @@ func SettingsValues(st models.Settings) map[string]any {
"url_host": st.URLHost,
"url_slash": st.URLSlash,
"url_lowercase": st.URLLowercase,
"links_new_tab": st.LinksNewTab,
"nofollow_domains": st.NofollowDomains,
"sponsored_domains": st.SponsoredDomains,
"verify_google": st.VerifyGoogle,
"verify_bing": st.VerifyBing,
"verify_yandex": st.VerifyYandex,
@@ -119,12 +123,22 @@ func SetSettingsValue(st *models.Settings, column string, v any) error {
st.VerifyYandex, err = text()
case "csv_delimiter":
st.CSVDelimiter, err = text()
case "nofollow_domains":
st.NofollowDomains, err = text()
case "sponsored_domains":
st.SponsoredDomains, err = text()
case "url_lowercase":
b, ok := v.(bool)
if !ok {
return fmt.Errorf("golem15.seo: settings %s is not a bool", column)
}
st.URLLowercase = b
case "links_new_tab":
b, ok := v.(bool)
if !ok {
return fmt.Errorf("golem15.seo: settings %s is not a bool", column)
}
st.LinksNewTab = b
case "query_params":
var out []models.QueryParam
if err = list(&out); err == nil {
@@ -256,6 +270,8 @@ func (s *Service) SaveSettings(ctx context.Context, tx *gorm.DB, in SettingsWrit
if len(problems) > 0 {
return models.Settings{}, &ProblemsError{Problems: problems}
}
row.NofollowDomains = models.NormalizeDomains(row.NofollowDomains)
row.SponsoredDomains = models.NormalizeDomains(row.SponsoredDomains)
now := time.Now().UTC()
row.UpdatedAt = &now
if err := tx.Save(&row).Error; err != nil {