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

@@ -25,6 +25,9 @@ type UpdateSettingsInput struct {
URLHost *string `json:"url_host,omitempty" jsonschema:"keep, www or bare"`
URLSlash *string `json:"url_slash,omitempty" jsonschema:"keep, add or remove a trailing slash"`
URLLowercase *bool `json:"url_lowercase,omitempty" jsonschema:"lowercase the ASCII letters of addresses"`
LinksNewTab *bool `json:"links_new_tab,omitempty" jsonschema:"open links to other sites in a new tab (rel=noopener, announced to screen readers); default true"`
NofollowDomains *string `json:"nofollow_domains,omitempty" jsonschema:"domains whose links always get nofollow, one per line, e.g. example.com (subdomains included; no https:// and no path)"`
SponsoredDomains *string `json:"sponsored_domains,omitempty" jsonschema:"domains whose links always get sponsored, one per line (subdomains included)"`
VerifyGoogle *string `json:"verify_google,omitempty" jsonschema:"the Google Search Console verification code"`
VerifyBing *string `json:"verify_bing,omitempty" jsonschema:"the Bing verification code"`
VerifyYandex *string `json:"verify_yandex,omitempty" jsonschema:"the Yandex verification code"`

View File

@@ -63,7 +63,12 @@ func (c settingsAdminController) FormBeforeUpdate(ctx context.Context, model any
if !ok || s == nil {
return nil
}
return problemsError(ctx, translator(c.app), s.Problems())
if err := problemsError(ctx, translator(c.app), s.Problems()); err != nil {
return err
}
s.NofollowDomains = models.NormalizeDomains(s.NofollowDomains)
s.SponsoredDomains = models.NormalizeDomains(s.SponsoredDomains)
return nil
}
// FormBeforeCreate checks a created row like an update.