mirror of
https://github.com/gohugoio/hugo.git
synced 2024-12-04 21:22:51 -05:00
e917401c71
Fixes #13063
259 lines
6.8 KiB
Go
259 lines
6.8 KiB
Go
// Copyright 2019 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 (
|
|
"fmt"
|
|
"strings"
|
|
"sync"
|
|
"sync/atomic"
|
|
|
|
"github.com/gohugoio/hugo/hugofs/files"
|
|
"github.com/gohugoio/hugo/resources"
|
|
|
|
"github.com/gohugoio/hugo/common/maps"
|
|
"github.com/gohugoio/hugo/common/paths"
|
|
|
|
"github.com/gohugoio/hugo/lazy"
|
|
|
|
"github.com/gohugoio/hugo/resources/kinds"
|
|
"github.com/gohugoio/hugo/resources/page"
|
|
"github.com/gohugoio/hugo/resources/page/pagemeta"
|
|
)
|
|
|
|
var pageIDCounter atomic.Uint64
|
|
|
|
func (h *HugoSites) newPage(m *pageMeta) (*pageState, *paths.Path, error) {
|
|
p, pth, err := h.doNewPage(m)
|
|
if err != nil {
|
|
// Make sure that any partially created page part is marked as stale.
|
|
m.MarkStale()
|
|
}
|
|
return p, pth, err
|
|
}
|
|
|
|
func (h *HugoSites) doNewPage(m *pageMeta) (*pageState, *paths.Path, error) {
|
|
m.Staler = &resources.AtomicStaler{}
|
|
if m.pageMetaParams == nil {
|
|
m.pageMetaParams = &pageMetaParams{
|
|
pageConfig: &pagemeta.PageConfig{},
|
|
}
|
|
}
|
|
if m.pageConfig.Params == nil {
|
|
m.pageConfig.Params = maps.Params{}
|
|
}
|
|
|
|
pid := pageIDCounter.Add(1)
|
|
pi, err := m.parseFrontMatter(h, pid)
|
|
if err != nil {
|
|
return nil, nil, err
|
|
}
|
|
|
|
if err := m.setMetaPre(pi, h.Log, h.Conf); err != nil {
|
|
return nil, nil, m.wrapError(err, h.BaseFs.SourceFs)
|
|
}
|
|
pcfg := m.pageConfig
|
|
if pcfg.Lang != "" {
|
|
if h.Conf.IsLangDisabled(pcfg.Lang) {
|
|
return nil, nil, nil
|
|
}
|
|
}
|
|
|
|
if pcfg.Path != "" {
|
|
s := m.pageConfig.Path
|
|
// Paths from content adapters should never have any extension.
|
|
if pcfg.IsFromContentAdapter || !paths.HasExt(s) {
|
|
var (
|
|
isBranch bool
|
|
isBranchSet bool
|
|
ext string = m.pageConfig.ContentMediaType.FirstSuffix.Suffix
|
|
)
|
|
if pcfg.Kind != "" {
|
|
isBranch = kinds.IsBranch(pcfg.Kind)
|
|
isBranchSet = true
|
|
}
|
|
|
|
if !pcfg.IsFromContentAdapter {
|
|
if m.pathInfo != nil {
|
|
if !isBranchSet {
|
|
isBranch = m.pathInfo.IsBranchBundle()
|
|
}
|
|
if m.pathInfo.Ext() != "" {
|
|
ext = m.pathInfo.Ext()
|
|
}
|
|
} else if m.f != nil {
|
|
pi := m.f.FileInfo().Meta().PathInfo
|
|
if !isBranchSet {
|
|
isBranch = pi.IsBranchBundle()
|
|
}
|
|
if pi.Ext() != "" {
|
|
ext = pi.Ext()
|
|
}
|
|
}
|
|
}
|
|
|
|
if isBranch {
|
|
s += "/_index." + ext
|
|
} else {
|
|
s += "/index." + ext
|
|
}
|
|
|
|
}
|
|
m.pathInfo = h.Conf.PathParser().Parse(files.ComponentFolderContent, s)
|
|
} else if m.pathInfo == nil {
|
|
if m.f != nil {
|
|
m.pathInfo = m.f.FileInfo().Meta().PathInfo
|
|
}
|
|
|
|
if m.pathInfo == nil {
|
|
panic(fmt.Sprintf("missing pathInfo in %v", m))
|
|
}
|
|
}
|
|
|
|
ps, err := func() (*pageState, error) {
|
|
if m.s == nil {
|
|
// Identify the Site/language to associate this Page with.
|
|
var lang string
|
|
if pcfg.Lang != "" {
|
|
lang = pcfg.Lang
|
|
} else if m.f != nil {
|
|
meta := m.f.FileInfo().Meta()
|
|
lang = meta.Lang
|
|
} else {
|
|
lang = m.pathInfo.Lang()
|
|
}
|
|
|
|
m.s = h.resolveSite(lang)
|
|
|
|
if m.s == nil {
|
|
return nil, fmt.Errorf("no site found for language %q", lang)
|
|
}
|
|
}
|
|
|
|
var tc viewName
|
|
// Identify Page Kind.
|
|
if m.pageConfig.Kind == "" {
|
|
m.pageConfig.Kind = kinds.KindSection
|
|
if m.pathInfo.Base() == "/" {
|
|
m.pageConfig.Kind = kinds.KindHome
|
|
} else if m.pathInfo.IsBranchBundle() {
|
|
// A section, taxonomy or term.
|
|
tc = m.s.pageMap.cfg.getTaxonomyConfig(m.Path())
|
|
if !tc.IsZero() {
|
|
// Either a taxonomy or a term.
|
|
if tc.pluralTreeKey == m.Path() {
|
|
m.pageConfig.Kind = kinds.KindTaxonomy
|
|
} else {
|
|
m.pageConfig.Kind = kinds.KindTerm
|
|
}
|
|
}
|
|
} else if m.f != nil {
|
|
m.pageConfig.Kind = kinds.KindPage
|
|
}
|
|
}
|
|
|
|
if m.pageConfig.Kind == kinds.KindTerm || m.pageConfig.Kind == kinds.KindTaxonomy {
|
|
if tc.IsZero() {
|
|
tc = m.s.pageMap.cfg.getTaxonomyConfig(m.Path())
|
|
}
|
|
if tc.IsZero() {
|
|
return nil, fmt.Errorf("no taxonomy configuration found for %q", m.Path())
|
|
}
|
|
m.singular = tc.singular
|
|
if m.pageConfig.Kind == kinds.KindTerm {
|
|
m.term = paths.TrimLeading(strings.TrimPrefix(m.pathInfo.Unnormalized().Base(), tc.pluralTreeKey))
|
|
}
|
|
}
|
|
|
|
if m.pageConfig.Kind == kinds.KindPage && !m.s.conf.IsKindEnabled(m.pageConfig.Kind) {
|
|
return nil, nil
|
|
}
|
|
|
|
// Parse the rest of the page content.
|
|
m.content, err = m.newCachedContent(h, pi)
|
|
if err != nil {
|
|
return nil, m.wrapError(err, h.SourceFs)
|
|
}
|
|
|
|
ps := &pageState{
|
|
pid: pid,
|
|
pageOutput: nopPageOutput,
|
|
pageOutputTemplateVariationsState: &atomic.Uint32{},
|
|
resourcesPublishInit: &sync.Once{},
|
|
Staler: m,
|
|
dependencyManager: m.s.Conf.NewIdentityManager(m.Path()),
|
|
pageCommon: &pageCommon{
|
|
FileProvider: m,
|
|
store: maps.NewScratch(),
|
|
Positioner: page.NopPage,
|
|
InSectionPositioner: page.NopPage,
|
|
ResourceNameTitleProvider: m,
|
|
ResourceParamsProvider: m,
|
|
PageMetaProvider: m,
|
|
PageMetaInternalProvider: m,
|
|
RelatedKeywordsProvider: m,
|
|
OutputFormatsProvider: page.NopPage,
|
|
ResourceTypeProvider: pageTypesProvider,
|
|
MediaTypeProvider: pageTypesProvider,
|
|
RefProvider: page.NopPage,
|
|
ShortcodeInfoProvider: page.NopPage,
|
|
LanguageProvider: m.s,
|
|
|
|
InternalDependencies: m.s,
|
|
init: lazy.New(),
|
|
m: m,
|
|
s: m.s,
|
|
sWrapped: page.WrapSite(m.s),
|
|
},
|
|
}
|
|
|
|
if m.f != nil {
|
|
gi, err := m.s.h.gitInfoForPage(ps)
|
|
if err != nil {
|
|
return nil, fmt.Errorf("failed to load Git data: %w", err)
|
|
}
|
|
ps.gitInfo = gi
|
|
owners, err := m.s.h.codeownersForPage(ps)
|
|
if err != nil {
|
|
return nil, fmt.Errorf("failed to load CODEOWNERS: %w", err)
|
|
}
|
|
ps.codeowners = owners
|
|
}
|
|
|
|
ps.pageMenus = &pageMenus{p: ps}
|
|
ps.PageMenusProvider = ps.pageMenus
|
|
ps.GetPageProvider = pageSiteAdapter{s: m.s, p: ps}
|
|
ps.GitInfoProvider = ps
|
|
ps.TranslationsProvider = ps
|
|
ps.ResourceDataProvider = &pageData{pageState: ps}
|
|
ps.RawContentProvider = ps
|
|
ps.ChildCareProvider = ps
|
|
ps.TreeProvider = pageTree{p: ps}
|
|
ps.Eqer = ps
|
|
ps.TranslationKeyProvider = ps
|
|
ps.ShortcodeInfoProvider = ps
|
|
ps.AlternativeOutputFormatsProvider = ps
|
|
|
|
if err := ps.initLazyProviders(); err != nil {
|
|
return nil, ps.wrapError(err)
|
|
}
|
|
return ps, nil
|
|
}()
|
|
|
|
if ps == nil {
|
|
return nil, nil, err
|
|
}
|
|
|
|
return ps, ps.PathInfo(), err
|
|
}
|