diff options
Diffstat (limited to 'hugolib/site_new.go')
-rw-r--r-- | hugolib/site_new.go | 603 |
1 files changed, 0 insertions, 603 deletions
diff --git a/hugolib/site_new.go b/hugolib/site_new.go deleted file mode 100644 index 19a7e42d7..000000000 --- a/hugolib/site_new.go +++ /dev/null @@ -1,603 +0,0 @@ -// Copyright 2024 The Hugo Authors. All rights reserved. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -package hugolib - -import ( - "context" - "errors" - "fmt" - "html/template" - "os" - "path/filepath" - "sort" - "time" - - "github.com/bep/logg" - "github.com/gohugoio/hugo/cache/dynacache" - "github.com/gohugoio/hugo/common/hugo" - "github.com/gohugoio/hugo/common/loggers" - "github.com/gohugoio/hugo/common/maps" - "github.com/gohugoio/hugo/common/para" - "github.com/gohugoio/hugo/config" - "github.com/gohugoio/hugo/config/allconfig" - "github.com/gohugoio/hugo/deps" - "github.com/gohugoio/hugo/hugolib/doctree" - "github.com/gohugoio/hugo/hugolib/pagesfromdata" - "github.com/gohugoio/hugo/identity" - "github.com/gohugoio/hugo/internal/warpc" - "github.com/gohugoio/hugo/langs" - "github.com/gohugoio/hugo/langs/i18n" - "github.com/gohugoio/hugo/lazy" - "github.com/gohugoio/hugo/modules" - "github.com/gohugoio/hugo/navigation" - "github.com/gohugoio/hugo/output" - "github.com/gohugoio/hugo/publisher" - "github.com/gohugoio/hugo/resources" - "github.com/gohugoio/hugo/resources/page" - "github.com/gohugoio/hugo/resources/page/pagemeta" - "github.com/gohugoio/hugo/resources/page/siteidentities" - "github.com/gohugoio/hugo/resources/resource" - "github.com/gohugoio/hugo/tpl" - "github.com/gohugoio/hugo/tpl/tplimpl" -) - -var _ page.Site = (*Site)(nil) - -type siteState int - -const ( - siteStateInit siteState = iota - siteStateReady -) - -type Site struct { - state siteState - conf *allconfig.Config - language *langs.Language - languagei int - pageMap *pageMap - - // The owning container. - h *HugoSites - - *deps.Deps - - // Page navigation. - *pageFinder - taxonomies page.TaxonomyList - 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 - - relatedDocsHandler *page.RelatedDocsHandler - siteRefLinker - publisher publisher.Publisher - frontmatterHandler pagemeta.FrontMatterHandler - - // 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 - - // Lazily loaded site dependencies - init *siteInit -} - -func (s *Site) Debug() { - fmt.Println("Debugging site", s.Lang(), "=>") - // fmt.Println(s.pageMap.testDump()) -} - -// NewHugoSites creates HugoSites from the given config. -func NewHugoSites(cfg deps.DepsCfg) (*HugoSites, error) { - conf := cfg.Configs.GetFirstLanguageConfig() - - var logger loggers.Logger - if cfg.TestLogger != nil { - logger = cfg.TestLogger - } else { - var logHookLast func(e *logg.Entry) error - if cfg.Configs.Base.PanicOnWarning { - logHookLast = loggers.PanicOnWarningHook - } - if cfg.LogOut == nil { - cfg.LogOut = os.Stdout - } - if cfg.LogLevel == 0 { - cfg.LogLevel = logg.LevelWarn - } - - logOpts := loggers.Options{ - Level: cfg.LogLevel, - DistinctLevel: logg.LevelWarn, // This will drop duplicate log warning and errors. - HandlerPost: logHookLast, - Stdout: cfg.LogOut, - Stderr: cfg.LogOut, - StoreErrors: conf.Watching(), - SuppressStatements: conf.IgnoredLogs(), - } - logger = loggers.New(logOpts) - - } - - memCache := dynacache.New(dynacache.Options{Watching: conf.Watching(), Log: logger}) - - var h *HugoSites - onSignalRebuild := func(ids ...identity.Identity) { - // This channel is buffered, but make sure we do this in a non-blocking way. - if cfg.ChangesFromBuild != nil { - go func() { - cfg.ChangesFromBuild <- ids - }() - } - } - - firstSiteDeps := &deps.Deps{ - Fs: cfg.Fs, - Log: logger, - Conf: conf, - BuildState: &deps.BuildState{ - OnSignalRebuild: onSignalRebuild, - }, - MemCache: memCache, - TemplateProvider: tplimpl.DefaultTemplateProvider, - TranslationProvider: i18n.NewTranslationProvider(), - WasmDispatchers: warpc.AllDispatchers( - warpc.Options{ - CompilationCacheDir: filepath.Join(conf.Dirs().CacheDir, "_warpc"), - - // Katex is relatively slow. - PoolSize: 8, - Infof: logger.InfoCommand("wasm").Logf, - }, - ), - } - - if err := firstSiteDeps.Init(); err != nil { - return nil, err - } - - confm := cfg.Configs - if err := confm.Validate(logger); err != nil { - return nil, err - } - var sites []*Site - - ns := &contentNodeShifter{ - numLanguages: len(confm.Languages), - } - - treeConfig := doctree.Config[contentNodeI]{ - Shifter: ns, - } - - pageTrees := &pageTrees{ - treePages: doctree.New( - treeConfig, - ), - treeResources: doctree.New( - treeConfig, - ), - treeTaxonomyEntries: doctree.NewTreeShiftTree[*weightedContentNode](doctree.DimensionLanguage.Index(), len(confm.Languages)), - treePagesFromTemplateAdapters: doctree.NewTreeShiftTree[*pagesfromdata.PagesFromTemplate](doctree.DimensionLanguage.Index(), len(confm.Languages)), - } - - pageTrees.createMutableTrees() - - for i, confp := range confm.ConfigLangs() { - language := confp.Language() - if language.Disabled { - continue - } - k := language.Lang - conf := confm.LanguageConfigMap[k] - frontmatterHandler, err := pagemeta.NewFrontmatterHandler(firstSiteDeps.Log, conf.Frontmatter) - if err != nil { - return nil, err - } - - langs.SetParams(language, conf.Params) - - s := &Site{ - conf: conf, - language: language, - languagei: i, - frontmatterHandler: frontmatterHandler, - } - - if i == 0 { - firstSiteDeps.Site = s - s.Deps = firstSiteDeps - } else { - d, err := firstSiteDeps.Clone(s, confp) - if err != nil { - return nil, err - } - s.Deps = d - } - - s.pageMap = newPageMap(i, s, memCache, pageTrees) - - s.pageFinder = newPageFinder(s.pageMap) - s.siteRefLinker, err = newSiteRefLinker(s) - if err != nil { - return nil, err - } - // Set up the main publishing chain. - pub, err := publisher.NewDestinationPublisher( - firstSiteDeps.ResourceSpec, - s.conf.OutputFormats.Config, - s.conf.MediaTypes.Config, - ) - if err != nil { - return nil, err - } - - s.publisher = pub - s.relatedDocsHandler = page.NewRelatedDocsHandler(s.conf.Related) - // Site deps end. - - s.prepareInits() - sites = append(sites, s) - } - - if len(sites) == 0 { - return nil, errors.New("no sites to build") - } - - // Pull the default content language to the top, then sort the sites by language weight (if set) or lang. - defaultContentLanguage := confm.Base.DefaultContentLanguage - sort.Slice(sites, func(i, j int) bool { - li := sites[i].language - lj := sites[j].language - if li.Lang == defaultContentLanguage { - return true - } - - if lj.Lang == defaultContentLanguage { - return false - } - - if li.Weight != lj.Weight { - return li.Weight < lj.Weight - } - return li.Lang < lj.Lang - }) - - var err error - h, err = newHugoSites(cfg, firstSiteDeps, pageTrees, sites) - if err == nil && h == nil { - panic("hugo: newHugoSitesNew returned nil error and nil HugoSites") - } - - return h, err -} - -func newHugoSites(cfg deps.DepsCfg, d *deps.Deps, pageTrees *pageTrees, sites []*Site) (*HugoSites, error) { - numWorkers := config.GetNumWorkerMultiplier() - numWorkersSite := numWorkers - if numWorkersSite > len(sites) { - numWorkersSite = len(sites) - } - workersSite := para.New(numWorkersSite) - - h := &HugoSites{ - Sites: sites, - Deps: sites[0].Deps, - Configs: cfg.Configs, - workersSite: workersSite, - numWorkersSites: numWorkers, - numWorkers: numWorkers, - pageTrees: pageTrees, - cachePages: dynacache.GetOrCreatePartition[string, - page.Pages](d.MemCache, "/pags/all", - dynacache.OptionsPartition{Weight: 10, ClearWhen: dynacache.ClearOnRebuild}, - ), - cacheContentSource: dynacache.GetOrCreatePartition[string, *resources.StaleValue[[]byte]](d.MemCache, "/cont/src", dynacache.OptionsPartition{Weight: 70, ClearWhen: dynacache.ClearOnChange}), - translationKeyPages: maps.NewSliceCache[page.Page](), - currentSite: sites[0], - skipRebuildForFilenames: make(map[string]bool), - init: &hugoSitesInit{ - data: lazy.New(), - layouts: lazy.New(), - gitInfo: lazy.New(), - }, - } - - // Assemble dependencies to be used in hugo.Deps. - var dependencies []*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 d.Paths.AllModules() { - dependencies = append(dependencies, depFromMod(m)) - } - - h.hugoInfo = hugo.NewInfo(h.Configs.GetFirstLanguageConfig(), dependencies) - - var prototype *deps.Deps - for i, s := range sites { - s.h = h - if err := s.Deps.Compile(prototype); err != nil { - return nil, err - } - if i == 0 { - prototype = s.Deps - } - } - - h.fatalErrorHandler = &fatalErrorHandler{ - h: h, - donec: make(chan bool), - } - - h.init.data.Add(func(context.Context) (any, error) { - err := h.loadData() - if err != nil { - return nil, fmt.Errorf("failed to load data: %w", err) - } - return nil, nil - }) - - h.init.layouts.Add(func(context.Context) (any, error) { - for _, s := range h.Sites { - if err := s.Tmpl().(tpl.TemplateManager).MarkReady(); err != nil { - return nil, err - } - } - return nil, nil - }) - - h.init.gitInfo.Add(func(context.Context) (any, error) { - err := h.loadGitInfo() - if err != nil { - return nil, fmt.Errorf("failed to load Git info: %w", err) - } - return nil, nil - }) - - return h, nil -} - -// Deprecated: Use hugo.IsServer instead. -func (s *Site) IsServer() bool { - hugo.Deprecate(".Site.IsServer", "Use hugo.IsServer instead.", "v0.120.0") - return s.conf.Internal.Running -} - -// Returns the server port. -func (s *Site) ServerPort() int { - return s.conf.C.BaseURL.Port() -} - -// Returns the configured title for this Site. -func (s *Site) Title() string { - return s.conf.Title -} - -func (s *Site) Copyright() string { - return s.conf.Copyright -} - -// Deprecated: Use .Site.Home.OutputFormats.Get "rss" instead. -func (s *Site) RSSLink() template.URL { - hugo.Deprecate(".Site.RSSLink", "Use the Output Format's Permalink method instead, e.g. .OutputFormats.Get \"RSS\".Permalink", "v0.114.0") - rssOutputFormat := s.home.OutputFormats().Get("rss") - return template.URL(rssOutputFormat.Permalink()) -} - -func (s *Site) Config() page.SiteConfig { - return page.SiteConfig{ - Privacy: s.conf.Privacy, - Services: s.conf.Services, - } -} - -func (s *Site) LanguageCode() string { - return s.Language().LanguageCode() -} - -// Returns all Sites for all languages. -func (s *Site) Sites() page.Sites { - sites := make(page.Sites, len(s.h.Sites)) - for i, s := range s.h.Sites { - sites[i] = s.Site() - } - return sites -} - -// Returns Site currently rendering. -func (s *Site) Current() page.Site { - return s.h.currentSite -} - -// MainSections returns the list of main sections. -func (s *Site) MainSections() []string { - s.CheckReady() - return s.conf.C.MainSections -} - -// Returns a struct with some information about the build. -func (s *Site) Hugo() hugo.HugoInfo { - if s.h == nil || s.h.hugoInfo.Environment == "" { - panic("site: hugo: hugoInfo not initialized") - } - return s.h.hugoInfo -} - -// Returns the BaseURL for this Site. -func (s *Site) BaseURL() string { - return s.conf.C.BaseURL.WithPath -} - -// Deprecated: Use .Site.Lastmod instead. -func (s *Site) LastChange() time.Time { - s.CheckReady() - hugo.Deprecate(".Site.LastChange", "Use .Site.Lastmod instead.", "v0.123.0") - return s.lastmod -} - -// Returns the last modification date of the content. -func (s *Site) Lastmod() time.Time { - return s.lastmod -} - -// Returns the Params configured for this site. -func (s *Site) Params() maps.Params { - return s.conf.Params -} - -// Deprecated: Use taxonomies instead. -func (s *Site) Author() map[string]any { - if len(s.conf.Author) != 0 { - hugo.Deprecate(".Site.Author", "Use taxonomies instead.", "v0.124.0") - } - return s.conf.Author -} - -// Deprecated: Use taxonomies instead. -func (s *Site) Authors() page.AuthorList { - hugo.Deprecate(".Site.Authors", "Use taxonomies instead.", "v0.124.0") - return page.AuthorList{} -} - -// Deprecated: Use .Site.Params instead. -func (s *Site) Social() map[string]string { - hugo.Deprecate(".Site.Social", "Use .Site.Params instead.", "v0.124.0") - return s.conf.Social -} - -// Deprecated: Use .Site.Config.Services.Disqus.Shortname instead. -func (s *Site) DisqusShortname() string { - hugo.Deprecate(".Site.DisqusShortname", "Use .Site.Config.Services.Disqus.Shortname instead.", "v0.120.0") - return s.Config().Services.Disqus.Shortname -} - -// Deprecated: Use .Site.Config.Services.GoogleAnalytics.ID instead. -func (s *Site) GoogleAnalytics() string { - hugo.Deprecate(".Site.GoogleAnalytics", "Use .Site.Config.Services.GoogleAnalytics.ID instead.", "v0.120.0") - return s.Config().Services.GoogleAnalytics.ID -} - -func (s *Site) Param(key any) (any, error) { - return resource.Param(s, nil, key) -} - -// Returns a map of all the data inside /data. -func (s *Site) Data() map[string]any { - return s.s.h.Data() -} - -func (s *Site) BuildDrafts() bool { - return s.conf.BuildDrafts -} - -// Deprecated: Use hugo.IsMultilingual instead. -func (s *Site) IsMultiLingual() bool { - hugo.Deprecate(".Site.IsMultiLingual", "Use hugo.IsMultilingual instead.", "v0.124.0") - return s.h.isMultilingual() -} - -func (s *Site) LanguagePrefix() string { - prefix := s.GetLanguagePrefix() - if prefix == "" { - return "" - } - return "/" + prefix -} - -func (s *Site) Site() page.Site { - return page.WrapSite(s) -} - -func (s *Site) ForEeachIdentityByName(name string, f func(identity.Identity) bool) { - if id, found := siteidentities.FromString(name); found { - if f(id) { - return - } - } -} - -// Pages returns all pages. -// This is for the current language only. -func (s *Site) Pages() page.Pages { - s.CheckReady() - return s.pageMap.getPagesInSection( - pageMapQueryPagesInSection{ - pageMapQueryPagesBelowPath: pageMapQueryPagesBelowPath{ - Path: "", - KeyPart: "global", - Include: pagePredicates.ShouldListGlobal, - }, - Recursive: true, - IncludeSelf: true, - }, - ) -} - -// RegularPages returns all the regular pages. -// This is for the current language only. -func (s *Site) RegularPages() page.Pages { - s.CheckReady() - return s.pageMap.getPagesInSection( - pageMapQueryPagesInSection{ - pageMapQueryPagesBelowPath: pageMapQueryPagesBelowPath{ - Path: "", - KeyPart: "global", - Include: pagePredicates.ShouldListGlobal.And(pagePredicates.KindPage), - }, - Recursive: true, - }, - ) -} - -// AllPages returns all pages for all sites. -func (s *Site) AllPages() page.Pages { - s.CheckReady() - return s.h.Pages() -} - -// AllRegularPages returns all regular pages for all sites. -func (s *Site) AllRegularPages() page.Pages { - s.CheckReady() - return s.h.RegularPages() -} - -func (s *Site) CheckReady() { - if s.state != siteStateReady { - panic("this method cannot be called before the site is fully initialized") - } -} |