summaryrefslogtreecommitdiffstats
path: root/hugolib/site.go
diff options
context:
space:
mode:
authorBjørn Erik Pedersen <bjorn.erik.pedersen@gmail.com>2023-01-04 18:24:36 +0100
committerBjørn Erik Pedersen <bjorn.erik.pedersen@gmail.com>2023-05-16 18:01:29 +0200
commit241b21b0fd34d91fccb2ce69874110dceae6f926 (patch)
treed4e0118eac7e9c42f065815447a70805f8d6ad3e /hugolib/site.go
parent6aededf6b42011c3039f5f66487a89a8dd65e0e7 (diff)
Create a struct with all of Hugo's config options
Primary motivation is documentation, but it will also hopefully simplify the code. Also, * Lower case the default output format names; this is in line with the custom ones (map keys) and how it's treated all the places. This avoids doing `stringds.EqualFold` everywhere. Closes #10896 Closes #10620
Diffstat (limited to 'hugolib/site.go')
-rw-r--r--hugolib/site.go847
1 files changed, 77 insertions, 770 deletions
diff --git a/hugolib/site.go b/hugolib/site.go
index 1b0c48cbc..b055cf690 100644
--- a/hugolib/site.go
+++ b/hugolib/site.go
@@ -16,7 +16,6 @@ package hugolib
import (
"context"
"fmt"
- "html/template"
"io"
"log"
"mime"
@@ -26,7 +25,6 @@ import (
"regexp"
"runtime"
"sort"
- "strconv"
"strings"
"time"
@@ -34,23 +32,16 @@ import (
"github.com/gohugoio/hugo/common/htime"
"github.com/gohugoio/hugo/common/hugio"
"github.com/gohugoio/hugo/common/types"
- "github.com/gohugoio/hugo/modules"
"golang.org/x/text/unicode/norm"
"github.com/gohugoio/hugo/common/paths"
- "github.com/gohugoio/hugo/common/constants"
-
- "github.com/gohugoio/hugo/common/loggers"
-
"github.com/gohugoio/hugo/resources"
"github.com/gohugoio/hugo/identity"
"github.com/gohugoio/hugo/markup/converter/hooks"
- "github.com/gohugoio/hugo/resources/resource"
-
"github.com/gohugoio/hugo/markup/converter"
"github.com/gohugoio/hugo/hugofs/files"
@@ -59,7 +50,6 @@ import (
"github.com/gohugoio/hugo/common/text"
- "github.com/gohugoio/hugo/common/hugo"
"github.com/gohugoio/hugo/publisher"
"github.com/gohugoio/hugo/langs"
@@ -69,110 +59,18 @@ import (
"github.com/gohugoio/hugo/config"
"github.com/gohugoio/hugo/lazy"
- "github.com/gohugoio/hugo/media"
-
"github.com/fsnotify/fsnotify"
bp "github.com/gohugoio/hugo/bufferpool"
"github.com/gohugoio/hugo/deps"
"github.com/gohugoio/hugo/helpers"
"github.com/gohugoio/hugo/navigation"
"github.com/gohugoio/hugo/output"
- "github.com/gohugoio/hugo/related"
- "github.com/gohugoio/hugo/resources/page/pagemeta"
"github.com/gohugoio/hugo/source"
"github.com/gohugoio/hugo/tpl"
"github.com/spf13/afero"
- "github.com/spf13/cast"
)
-// Site contains all the information relevant for constructing a static
-// site. The basic flow of information is as follows:
-//
-// 1. A list of Files is parsed and then converted into Pages.
-//
-// 2. Pages contain sections (based on the file they were generated from),
-// aliases and slugs (included in a pages frontmatter) which are the
-// various targets that will get generated. There will be canonical
-// listing. The canonical path can be overruled based on a pattern.
-//
-// 3. Taxonomies are created via configuration and will present some aspect of
-// the final page and typically a perm url.
-//
-// 4. All Pages are passed through a template based on their desired
-// layout based on numerous different elements.
-//
-// 5. The entire collection of files is written to disk.
-type Site struct {
-
- // The owning container. When multiple languages, there will be multiple
- // sites .
- h *HugoSites
-
- *PageCollections
-
- taxonomies page.TaxonomyList
-
- Sections page.Taxonomy
- Info *SiteInfo
-
- language *langs.Language
- siteBucket *pagesMapBucket
-
- siteCfg siteConfigHolder
-
- disabledKinds map[string]bool
-
- // Output formats defined in site config per Page Kind, or some defaults
- // if not set.
- // Output formats defined in Page front matter will override these.
- outputFormats map[string]output.Formats
-
- // All the output formats and media types available for this site.
- // These values will be merged from the Hugo defaults, the site config and,
- // finally, the language settings.
- outputFormatsConfig output.Formats
- mediaTypesConfig media.Types
-
- siteConfigConfig SiteConfig
-
- // How to handle page front matter.
- frontmatterHandler pagemeta.FrontMatterHandler
-
- // We render each site for all the relevant output formats in serial with
- // this rendering context pointing to the current one.
- rc *siteRenderingContext
-
- // The output formats that we need to render this site in. This slice
- // will be fixed once set.
- // This will be the union of Site.Pages' outputFormats.
- // This slice will be sorted.
- renderFormats output.Formats
-
- // Logger etc.
- *deps.Deps `json:"-"`
-
- // The func used to title case titles.
- titleFunc func(s string) string
-
- relatedDocsHandler *page.RelatedDocsHandler
- siteRefLinker
-
- publisher publisher.Publisher
-
- menus navigation.Menus
-
- // Shortcut to the home page. Note that this may be nil if
- // home page, for some odd reason, is disabled.
- home *pageState
-
- // The last modification date of this site.
- lastmod time.Time
-
- // Lazily loaded site dependencies
- init *siteInit
-}
-
func (s *Site) Taxonomies() page.TaxonomyList {
s.init.taxonomies.Do(context.Background())
return s.taxonomies
@@ -193,7 +91,7 @@ func (t taxonomiesConfig) Values() []viewName {
}
type siteConfigHolder struct {
- sitemap config.Sitemap
+ sitemap config.SitemapConfig
taxonomiesConfig taxonomiesConfig
timeout time.Duration
hasCJKLanguage bool
@@ -336,8 +234,13 @@ func (s *Site) Menus() navigation.Menus {
func (s *Site) initRenderFormats() {
formatSet := make(map[string]bool)
formats := output.Formats{}
+ rssDisabled := !s.conf.IsKindEnabled("rss")
s.pageMap.pageTrees.WalkRenderable(func(s string, n *contentNode) bool {
for _, f := range n.p.m.configuredOutputFormats {
+ if rssDisabled && f.Name == "rss" {
+ // legacy
+ continue
+ }
if !formatSet[f.Name] {
formats = append(formats, f)
formatSet[f.Name] = true
@@ -348,7 +251,7 @@ func (s *Site) initRenderFormats() {
// Add the per kind configured output formats
for _, kind := range allKindsInPages {
- if siteFormats, found := s.outputFormats[kind]; found {
+ if siteFormats, found := s.conf.C.KindOutputFormats[kind]; found {
for _, f := range siteFormats {
if !formatSet[f.Name] {
formats = append(formats, f)
@@ -374,443 +277,7 @@ func (s *Site) isEnabled(kind string) bool {
if kind == kindUnknown {
panic("Unknown kind")
}
- return !s.disabledKinds[kind]
-}
-
-// reset returns a new Site prepared for rebuild.
-func (s *Site) reset() *Site {
- return &Site{
- Deps: s.Deps,
- disabledKinds: s.disabledKinds,
- titleFunc: s.titleFunc,
- relatedDocsHandler: s.relatedDocsHandler.Clone(),
- siteRefLinker: s.siteRefLinker,
- outputFormats: s.outputFormats,
- rc: s.rc,
- outputFormatsConfig: s.outputFormatsConfig,
- frontmatterHandler: s.frontmatterHandler,
- mediaTypesConfig: s.mediaTypesConfig,
- language: s.language,
- siteBucket: s.siteBucket,
- h: s.h,
- publisher: s.publisher,
- siteConfigConfig: s.siteConfigConfig,
- init: s.init,
- PageCollections: s.PageCollections,
- siteCfg: s.siteCfg,
- }
-}
-
-// newSite creates a new site with the given configuration.
-func newSite(cfg deps.DepsCfg) (*Site, error) {
- if cfg.Language == nil {
- cfg.Language = langs.NewDefaultLanguage(cfg.Cfg)
- }
- if cfg.Logger == nil {
- panic("logger must be set")
- }
-
- ignoreErrors := cast.ToStringSlice(cfg.Language.Get("ignoreErrors"))
- ignorableLogger := loggers.NewIgnorableLogger(cfg.Logger, ignoreErrors...)
-
- disabledKinds := make(map[string]bool)
- for _, disabled := range cast.ToStringSlice(cfg.Language.Get("disableKinds")) {
- disabledKinds[disabled] = true
- }
-
- if disabledKinds["taxonomyTerm"] {
- // Correct from the value it had before Hugo 0.73.0.
- if disabledKinds[page.KindTaxonomy] {
- disabledKinds[page.KindTerm] = true
- } else {
- disabledKinds[page.KindTaxonomy] = true
- }
-
- delete(disabledKinds, "taxonomyTerm")
- } else if disabledKinds[page.KindTaxonomy] && !disabledKinds[page.KindTerm] {
- // This is a potentially ambiguous situation. It may be correct.
- ignorableLogger.Errorsf(constants.ErrIDAmbigousDisableKindTaxonomy, `You have the value 'taxonomy' in the disabledKinds list. In Hugo 0.73.0 we fixed these to be what most people expect (taxonomy and term).
-But this also means that your site configuration may not do what you expect. If it is correct, you can suppress this message by following the instructions below.`)
- }
-
- var (
- mediaTypesConfig []map[string]any
- outputFormatsConfig []map[string]any
-
- siteOutputFormatsConfig output.Formats
- siteMediaTypesConfig media.Types
- err error
- )
-
- // Add language last, if set, so it gets precedence.
- for _, cfg := range []config.Provider{cfg.Cfg, cfg.Language} {
- if cfg.IsSet("mediaTypes") {
- mediaTypesConfig = append(mediaTypesConfig, cfg.GetStringMap("mediaTypes"))
- }
- if cfg.IsSet("outputFormats") {
- outputFormatsConfig = append(outputFormatsConfig, cfg.GetStringMap("outputFormats"))
- }
- }
-
- siteMediaTypesConfig, err = media.DecodeTypes(mediaTypesConfig...)
- if err != nil {
- return nil, err
- }
-
- siteOutputFormatsConfig, err = output.DecodeFormats(siteMediaTypesConfig, outputFormatsConfig...)
- if err != nil {
- return nil, err
- }
-
- rssDisabled := disabledKinds[kindRSS]
- if rssDisabled {
- // Legacy
- tmp := siteOutputFormatsConfig[:0]
- for _, x := range siteOutputFormatsConfig {
- if !strings.EqualFold(x.Name, "rss") {
- tmp = append(tmp, x)
- }
- }
- siteOutputFormatsConfig = tmp
- }
-
- var siteOutputs map[string]any
- if cfg.Language.IsSet("outputs") {
- siteOutputs = cfg.Language.GetStringMap("outputs")
-
- // Check and correct taxonomy kinds vs pre Hugo 0.73.0.
- v1, hasTaxonomyTerm := siteOutputs["taxonomyterm"]
- v2, hasTaxonomy := siteOutputs[page.KindTaxonomy]
- _, hasTerm := siteOutputs[page.KindTerm]
- if hasTaxonomy && hasTaxonomyTerm {
- siteOutputs[page.KindTaxonomy] = v1
- siteOutputs[page.KindTerm] = v2
- delete(siteOutputs, "taxonomyTerm")
- } else if hasTaxonomy && !hasTerm {
- // This is a potentially ambiguous situation. It may be correct.
- ignorableLogger.Errorsf(constants.ErrIDAmbigousOutputKindTaxonomy, `You have configured output formats for 'taxonomy' in your site configuration. In Hugo 0.73.0 we fixed these to be what most people expect (taxonomy and term).
-But this also means that your site configuration may not do what you expect. If it is correct, you can suppress this message by following the instructions below.`)
- }
- if !hasTaxonomy && hasTaxonomyTerm {
- siteOutputs[page.KindTaxonomy] = v1
- delete(siteOutputs, "taxonomyterm")
- }
- }
-
- outputFormats, err := createSiteOutputFormats(siteOutputFormatsConfig, siteOutputs, rssDisabled)
- if err != nil {
- return nil, err
- }
-
- taxonomies := cfg.Language.GetStringMapString("taxonomies")
-
- var relatedContentConfig related.Config
-
- if cfg.Language.IsSet("related") {
- relatedContentConfig, err = related.DecodeConfig(cfg.Language.GetParams("related"))
- if err != nil {
- return nil, fmt.Errorf("failed to decode related config: %w", err)
- }
- } else {
- relatedContentConfig = related.DefaultConfig
- if _, found := taxonomies["tag"]; found {
- relatedContentConfig.Add(related.IndexConfig{Name: "tags", Weight: 80})
- }
- }
-
- titleFunc := helpers.GetTitleFunc(cfg.Language.GetString("titleCaseStyle"))
-
- frontMatterHandler, err := pagemeta.NewFrontmatterHandler(cfg.Logger, cfg.Cfg)
- if err != nil {
- return nil, err
- }
-
- timeout := 30 * time.Second
- if cfg.Language.IsSet("timeout") {
- v := cfg.Language.Get("timeout")
- d, err := types.ToDurationE(v)
- if err == nil {
- timeout = d
- }
- }
-
- siteConfig := siteConfigHolder{
- sitemap: config.DecodeSitemap(config.Sitemap{Priority: -1, Filename: "sitemap.xml"}, cfg.Language.GetStringMap("sitemap")),
- taxonomiesConfig: taxonomies,
- timeout: timeout,
- hasCJKLanguage: cfg.Language.GetBool("hasCJKLanguage"),
- enableEmoji: cfg.Language.Cfg.GetBool("enableEmoji"),
- }
-
- var siteBucket *pagesMapBucket
- if cfg.Language.IsSet("cascade") {
- var err error
- cascade, err := page.DecodeCascade(cfg.Language.Get("cascade"))
- if err != nil {
- return nil, fmt.Errorf("failed to decode cascade config: %s", err)
- }
-
- siteBucket = &pagesMapBucket{
- cascade: cascade,
- }
-
- }
-
- s := &Site{
- language: cfg.Language,
- siteBucket: siteBucket,
- disabledKinds: disabledKinds,
-
- outputFormats: outputFormats,
- outputFormatsConfig: siteOutputFormatsConfig,
- mediaTypesConfig: siteMediaTypesConfig,
-
- siteCfg: siteConfig,
-
- titleFunc: titleFunc,
-
- rc: &siteRenderingContext{output.HTMLFormat},
-
- frontmatterHandler: frontMatterHandler,
- relatedDocsHandler: page.NewRelatedDocsHandler(relatedContentConfig),
- }
-
- s.prepareInits()
-
- return s, nil
-}
-
-// NewSite creates a new site with the given dependency configuration.
-// The site will have a template system loaded and ready to use.
-// Note: This is mainly used in single site tests.
-func NewSite(cfg deps.DepsCfg) (*Site, error) {
- s, err := newSite(cfg)
- if err != nil {
- return nil, err
- }
-
- var l configLoader
- if err = l.applyDeps(cfg, s); err != nil {
- return nil, err
- }
-
- return s, nil
-}
-
-// NewSiteDefaultLang creates a new site in the default language.
-// The site will have a template system loaded and ready to use.
-// Note: This is mainly used in single site tests.
-// TODO(bep) test refactor -- remove
-func NewSiteDefaultLang(withTemplate ...func(templ tpl.TemplateManager) error) (*Site, error) {
- l := configLoader{cfg: config.New()}
- if err := l.applyConfigDefaults(); err != nil {
- return nil, err
- }
- return newSiteForLang(langs.NewDefaultLanguage(l.cfg), withTemplate...)
-}
-
-// NewEnglishSite creates a new site in English language.
-// The site will have a template system loaded and ready to use.
-// Note: This is mainly used in single site tests.
-// TODO(bep) test refactor -- remove
-func NewEnglishSite(withTemplate ...func(templ tpl.TemplateManager) error) (*Site, error) {
- l := configLoader{cfg: config.New()}
- if err := l.applyConfigDefaults(); err != nil {
- return nil, err
- }
- return newSiteForLang(langs.NewLanguage("en", l.cfg), withTemplate...)
-}
-
-// newSiteForLang creates a new site in the given language.
-func newSiteForLang(lang *langs.Language, withTemplate ...func(templ tpl.TemplateManager) error) (*Site, error) {
- withTemplates := func(templ tpl.TemplateManager) error {
- for _, wt := range withTemplate {
- if err := wt(templ); err != nil {
- return err
- }
- }
- return nil
- }
-
- cfg := deps.DepsCfg{WithTemplate: withTemplates, Cfg: lang}
-
- return NewSiteForCfg(cfg)
-}
-
-// NewSiteForCfg creates a new site for the given configuration.
-// The site will have a template system loaded and ready to use.
-// Note: This is mainly used in single site tests.
-func NewSiteForCfg(cfg deps.DepsCfg) (*Site, error) {
- h, err := NewHugoSites(cfg)
- if err != nil {
- return nil, err
- }
- return h.Sites[0], nil
-}
-
-type SiteInfo struct {
- Authors page.AuthorList
- Social SiteSocial
-
- hugoInfo hugo.Info
- title string
- RSSLink string
- Author map[string]any
- LanguageCode string
- Copyright string
-
- permalinks map[string]string
-
- LanguagePrefix string
- Languages langs.Languages
-
- BuildDrafts bool
-
- canonifyURLs bool
- relativeURLs bool
- uglyURLs func(p page.Page) bool
-
- owner *HugoSites
- s *Site
- language *langs.Language
- defaultContentLanguageInSubdir bool
- sectionPagesMenu string
-}
-
-func (s *SiteInfo) Pages() page.Pages {
- return s.s.Pages()
-}
-
-func (s *SiteInfo) RegularPages() page.Pages {
- return s.s.RegularPages()
-}
-
-func (s *SiteInfo) AllPages() page.Pages {
- return s.s.AllPages()
-}
-
-func (s *SiteInfo) AllRegularPages() page.Pages {
- return s.s.AllRegularPages()
-}
-
-func (s *SiteInfo) LastChange() time.Time {
- return s.s.lastmod
-}
-
-func (s *SiteInfo) Title() string {
- return s.title
-}
-
-func (s *SiteInfo) Site() page.Site {
- return s
-}
-
-func (s *SiteInfo) Menus() navigation.Menus {
- return s.s.Menus()
-}
-
-// TODO(bep) type
-func (s *SiteInfo) Taxonomies() page.TaxonomyList {
- return s.s.Taxonomies()
-}
-
-func (s *SiteInfo) Params() maps.Params {
- return s.s.Language().Params()
-}
-
-func (s *SiteInfo) Data() map[string]any {
- return s.s.h.Data()
-}
-
-func (s *SiteInfo) Language() *langs.Language {
- return s.language
-}
-
-func (s *SiteInfo) Config() SiteConfig {
- return s.s.siteConfigConfig
-}
-
-func (s *SiteInfo) Hugo() hugo.Info {
- return s.hugoInfo
-}
-
-// Sites is a convenience method to get all the Hugo sites/languages configured.
-func (s *SiteInfo) Sites() page.Sites {
- return s.s.h.siteInfos()
-}
-
-// Current returns the currently rendered Site.
-// If that isn't set yet, which is the situation before we start rendering,
-// if will return the Site itself.
-func (s *SiteInfo) Current() page.Site {
- if s.s.h.currentSite == nil {
- return s
- }
- return s.s.h.currentSite.Info
-}
-
-func (s *SiteInfo) String() string {
- return fmt.Sprintf("Site(%q)", s.title)
-}
-
-func (s *SiteInfo) BaseURL() template.URL {
- return template.URL(s.s.PathSpec.BaseURL.String())
-}
-
-// ServerPort returns the port part of the BaseURL, 0 if none found.
-func (s *SiteInfo) ServerPort() int {
- ps := s.s.PathSpec.BaseURL.URL().Port()
- if ps == "" {
- return 0
- }
- p, err := strconv.Atoi(ps)
- if err != nil {
- return 0
- }
- return p
-}
-
-// GoogleAnalytics is kept here for historic reasons.
-func (s *SiteInfo) GoogleAnalytics() string {
- return s.Config().Services.GoogleAnalytics.ID
-}
-
-// DisqusShortname is kept here for historic reasons.
-func (s *SiteInfo) DisqusShortname() string {
- return s.Config().Services.Disqus.Shortname
-}
-
-func (s *SiteInfo) GetIdentity() identity.Identity {
- return identity.KeyValueIdentity{Key: "site", Value: s.language.Lang}
-}
-
-// SiteSocial is a place to put social details on a site level. These are the
-// standard keys that themes will expect to have available, but can be
-// expanded to any others on a per site basis
-// github
-// facebook
-// facebook_admin
-// twitter
-// twitter_domain
-// pinterest
-// instagram
-// youtube
-// linkedin
-type SiteSocial map[string]string
-
-// Param is a convenience method to do lookups in SiteInfo's Params map.
-//
-// This method is also implemented on Page.
-func (s *SiteInfo) Param(key any) (any, error) {
- return resource.Param(s, nil, key)
-}
-
-func (s *SiteInfo) IsMultiLingual() bool {
- return len(s.Languages) > 1
-}
-
-func (s *SiteInfo) IsServer() bool {
- return s.owner.running
+ return s.conf.IsKindEnabled(kind)
}
type siteRefLinker struct {
@@ -820,11 +287,11 @@ type siteRefLinker struct {
notFoundURL string
}
-func newSiteRefLinker(cfg config.Provider, s *Site) (siteRefLinker, error) {
+func newSiteRefLinker(s *Site) (siteRefLinker, error) {
logger := s.Log.Error()
- notFoundURL := cfg.GetString("refLinksNotFoundURL")
- errLevel := cfg.GetString("refLinksErrorLevel")
+ notFoundURL := s.conf.RefLinksNotFoundURL
+ errLevel := s.conf.RefLinksErrorLevel
if strings.EqualFold(errLevel, "warning") {
logger = s.Log.Warn()
}
@@ -921,11 +388,7 @@ func (s *siteRefLinker) refLink(ref string, source any, relative bool, outputFor
}
func (s *Site) running() bool {
- return s.h != nil && s.h.running
-}
-
-func (s *Site) multilingual() *Multilingual {
- return s.h.multilingual
+ return s.h != nil && s.h.Configs.Base.Internal.Running
}
type whatChanged struct {
@@ -936,9 +399,9 @@ type whatChanged struct {
// RegisterMediaTypes will register the Site's media types in the mime
// package, so it will behave correctly with Hugo's built-in server.
func (s *Site) RegisterMediaTypes() {
- for _, mt := range s.mediaTypesConfig {
+ for _, mt := range s.conf.MediaTypes.Config {
for _, suffix := range mt.Suffixes() {
- _ = mime.AddExtensionType(mt.Delimiter+suffix, mt.Type()+"; charset=utf-8")
+ _ = mime.AddExtensionType(mt.Delimiter+suffix, mt.Type+"; charset=utf-8")
}
}
}
@@ -1131,31 +594,15 @@ func (s *Site) processPartial(config *BuildCfg, init func(config *BuildCfg) erro
}
if tmplChanged || i18nChanged {
- sites := s.h.Sites
- first := sites[0]
-
s.h.init.Reset()
-
- // TOD(bep) globals clean
- if err := first.Deps.LoadResources(); err != nil {
- return err
- }
-
- for i := 1; i < len(sites); i++ {
- site := sites[i]
- var err error
- depsCfg := deps.DepsCfg{
- Language: site.language,
- MediaTypes: site.mediaTypesConfig,
- OutputFormats: site.outputFormatsConfig,
- }
- site.Deps, err = first.Deps.ForLanguage(depsCfg, func(d *deps.Deps) error {
- d.Site = site.Info
- return nil
- })
- if err != nil {
+ var prototype *deps.Deps
+ for i, s := range s.h.Sites {
+ if err := s.Deps.Compile(prototype); err != nil {
return err
}
+ if i == 0 {
+ prototype = s.Deps
+ }
}
}
@@ -1215,10 +662,6 @@ func (s *Site) processPartial(config *BuildCfg, init func(config *BuildCfg) erro
}
func (s *Site) process(config BuildCfg) (err error) {
- if err = s.initialize(); err != nil {
- err = fmt.Errorf("initialize: %w", err)
- return
- }
if err = s.readAndProcessContent(config); err != nil {
err = fmt.Errorf("readAndProcessContent: %w", err)
return
@@ -1235,7 +678,7 @@ func (s *Site) render(ctx *siteRenderContext) (err error) {
// Note that even if disableAliases is set, the aliases themselves are
// preserved on page. The motivation with this is to be able to generate
// 301 redirects in a .htacess file and similar using a custom output format.
- if !s.Cfg.GetBool("disableAliases") {
+ if !s.conf.DisableAliases {
// Aliases must be rendered before pages.
// Some sites, Hugo docs included, have faulty alias definitions that point
// to itself or another real page. These will be overwritten in the next
@@ -1277,134 +720,25 @@ func (s *Site) render(ctx *siteRenderContext) (err error) {
return
}
-func (s *Site) Initialise() (err error) {
- return s.initialize()
-}
-
-func (s *Site) initialize() (err error) {
- return s.initializeSiteInfo()
-}
-
// HomeAbsURL is a convenience method giving the absolute URL to the home page.
-func (s *SiteInfo) HomeAbsURL() string {
+func (s *Site) HomeAbsURL() string {
base := ""
- if s.IsMultiLingual() {
+ if len(s.conf.Languages) > 1 {
base = s.Language().Lang
}
- return s.owner.AbsURL(base, false)
+ return s.AbsURL(base, false)
}
// SitemapAbsURL is a convenience method giving the absolute URL to the sitemap.
-func (s *SiteInfo) SitemapAbsURL() string {
+func (s *Site) SitemapAbsURL() string {
p := s.HomeAbsURL()
if !strings.HasSuffix(p, "/") {
p += "/"
}
- p += s.s.siteCfg.sitemap.Filename
+ p += s.conf.Sitemap.Filename
return p
}
-func (s *Site) initializeSiteInfo() error {
- var (
- lang = s.language
- languages langs.Languages
- )
-
- if s.h != nil && s.h.multilingual != nil {
- languages = s.h.multilingual.Languages
- }
-
- permalinks := s.Cfg.GetStringMapString("permalinks")
-
- defaultContentInSubDir := s.Cfg.GetBool("defaultContentLanguageInSubdir")
- defaultContentLanguage := s.Cfg.GetString("defaultContentLanguage")
-
- languagePrefix := ""
- if s.multilingualEnabled() && (defaultContentInSubDir || lang.Lang != defaultContentLanguage) {
- languagePrefix = "/" + lang.Lang
- }
-
- uglyURLs := func(p page.Page) bool {
- return false
- }
-
- v := s.Cfg.Get("uglyURLs")
- if v != nil {
- switch vv := v.(type) {
- case bool:
- uglyURLs = func(p page.Page) bool {
- return vv
- }
- case string:
- // Is what be get from CLI (--uglyURLs)
- vvv := cast.ToBool(vv)
- uglyURLs = func(p page.Page) bool {
- return vvv
- }
- default:
- m := maps.ToStringMapBool(v)
- uglyURLs = func(p page.Page) bool {
- return m[p.Section()]
- }
- }
- }
-
- // Assemble dependencies to be used in hugo.Deps.
- // TODO(bep) another reminder: We need to clean up this Site vs HugoSites construct.
- var deps []*hugo.Dependency
- var depFromMod func(m modules.Module) *hugo.Dependency
- depFromMod = func(m modules.Module) *hugo.Dependency {
- dep := &hugo.Dependency{
- Path: m.Path(),
- Version: m.Version(),
- Time: m.Time(),
- Vendor: m.Vendor(),
- }
-
- // These are pointers, but this all came from JSON so there's no recursive navigation,
- // so just create new values.
- if m.Replace() != nil {
- dep.Replace = depFromMod(m.Replace())
- }
- if m.Owner() != nil {
- dep.Owner = depFromMod(m.Owner())
- }
- return dep
- }
- for _, m := range s.Paths.AllModules {
- deps = append(deps, depFromMod(m))
- }
-
- s.Info = &SiteInfo{
- title: lang.GetString("title"),
- Author: lang.GetStringMap("author"),
- Social: lang.GetStringMapString("social"),
- LanguageCode: lang.GetString("languageCode"),
- Copyright: lang.GetString("copyright"),
- language: lang,
- LanguagePrefix: languagePrefix,
- Languages: languages,
- defaultContentLanguageInSubdir: defaultContentInSubDir,
- sectionPagesMenu: lang.GetString("sectionPagesMenu"),
- BuildDrafts: s.Cfg.GetBool("buildDrafts"),
- canonifyURLs: s.Cfg.GetBool("canonifyURLs"),
- relativeURLs: s.Cfg.GetBool("relativeURLs"),
- uglyURLs: uglyURLs,
- permalinks: permalinks,
- owner: s.h,
- s: s,
- hugoInfo: hugo.NewInfo(s.Cfg.GetString("environment"), deps),
- }
-
- rssOutputFormat, found := s.outputFormats[page.KindHome].GetByName(output.RSSFormat.Name)
-
- if found {
- s.Info.RSSLink = s.permalink(rssOutputFormat.BaseFilename())
- }
-
- return nil
-}
-
func (s *Site) eventToIdentity(e fsnotify.Event) (identity.PathIdentity, bool) {
for _, fs := range s.BaseFs.SourceFilesystems.FileSystems() {
if p := fs.Path(e.Name); p != "" {
@@ -1415,6 +749,10 @@ func (s *Site) eventToIdentity(e fsnotify.Event) (identity.PathIdentity, bool) {
}
func (s *Site) readAndProcessContent(buildConfig BuildCfg, filenames ...string) error {
+ if s.Deps == nil {
+ panic("nil deps on site")
+ }
+
sourceSpec := source.NewSourceSpec(s.PathSpec, buildConfig.ContentInclusionFilter, s.BaseFs.Content.Fs)
proc := newPagesProcessor(s.h, sourceSpec)
@@ -1428,58 +766,15 @@ func (s *Site) readAndProcessContent(buildConfig BuildCfg, filenames ...string)
return nil
}
-func (s *Site) getMenusFromConfig() navigation.Menus {
- ret := navigation.Menus{}
-
- if menus := s.language.GetStringMap("menus"); menus != nil {
- for name, menu := range menus {
- m, err := cast.ToSliceE(menu)
- if err != nil {
- s.Log.Errorf("menus in site config contain errors\n")
- s.Log.Errorln(err)
- } else {
- handleErr := func(err error) {
- if err == nil {
- return
- }
- s.Log.Errorf("menus in site config contain errors\n")
- s.Log.Errorln(err)
- }
-
- for _, entry := range m {
- s.Log.Debugf("found menu: %q, in site config\n", name)
-
- menuEntry := navigation.MenuEntry{Menu: name}
- ime, err := maps.ToStringMapE(entry)
- handleErr(err)
-
- err = menuEntry.MarshallMap(ime)
- handleErr(err)
-
- // TODO(bep) clean up all of this
- menuEntry.ConfiguredURL = s.Info.createNodeMenuEntryURL(menuEntry.ConfiguredURL)
-
- if ret[name] == nil {
- ret[name] = navigation.Menu{}
- }
- ret[name] = ret[name].Add(&menuEntry)
- }
- }
- }
- return ret
- }
- return ret
-}
-
-func (s *SiteInfo) createNodeMenuEntryURL(in string) string {
+func (s *Site) createNodeMenuEntryURL(in string) string {
if !strings.HasPrefix(in, "/") {
return in
}
// make it match the nodes
menuEntryURL := in
menuEntryURL = helpers.SanitizeURLKeepTrailingSlash(s.s.PathSpec.URLize(menuEntryURL))
- if !s.canonifyURLs {
- menuEntryURL = paths.AddContextRoot(s.s.PathSpec.BaseURL.String(), menuEntryURL)
+ if !s.conf.CanonifyURLs {
+ menuEntryURL = paths.AddContextRoot(s.s.PathSpec.Cfg.BaseURL().String(), menuEntryURL)
}
return menuEntryURL