hugo

Fork of github.com/gohugoio/hugo with reverse pagination support

git clone git://git.shimmy1996.com/hugo.git

page__new.go (5708B)

    1 // Copyright 2019 The Hugo Authors. All rights reserved.
    2 //
    3 // Licensed under the Apache License, Version 2.0 (the "License");
    4 // you may not use this file except in compliance with the License.
    5 // You may obtain a copy of the License at
    6 // http://www.apache.org/licenses/LICENSE-2.0
    7 //
    8 // Unless required by applicable law or agreed to in writing, software
    9 // distributed under the License is distributed on an "AS IS" BASIS,
   10 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
   11 // See the License for the specific language governing permissions and
   12 // limitations under the License.
   13 
   14 package hugolib
   15 
   16 import (
   17 	"html/template"
   18 	"strings"
   19 
   20 	"go.uber.org/atomic"
   21 
   22 	"github.com/gohugoio/hugo/common/hugo"
   23 
   24 	"github.com/gohugoio/hugo/common/maps"
   25 
   26 	"github.com/gohugoio/hugo/output"
   27 
   28 	"github.com/gohugoio/hugo/lazy"
   29 
   30 	"github.com/gohugoio/hugo/resources/page"
   31 )
   32 
   33 func newPageBase(metaProvider *pageMeta) (*pageState, error) {
   34 	if metaProvider.s == nil {
   35 		panic("must provide a Site")
   36 	}
   37 
   38 	s := metaProvider.s
   39 
   40 	ps := &pageState{
   41 		pageOutput:                        nopPageOutput,
   42 		pageOutputTemplateVariationsState: atomic.NewUint32(0),
   43 		pageCommon: &pageCommon{
   44 			FileProvider:            metaProvider,
   45 			AuthorProvider:          metaProvider,
   46 			Scratcher:               maps.NewScratcher(),
   47 			store:                   maps.NewScratch(),
   48 			Positioner:              page.NopPage,
   49 			InSectionPositioner:     page.NopPage,
   50 			ResourceMetaProvider:    metaProvider,
   51 			ResourceParamsProvider:  metaProvider,
   52 			PageMetaProvider:        metaProvider,
   53 			RelatedKeywordsProvider: metaProvider,
   54 			OutputFormatsProvider:   page.NopPage,
   55 			ResourceTypeProvider:    pageTypesProvider,
   56 			MediaTypeProvider:       pageTypesProvider,
   57 			RefProvider:             page.NopPage,
   58 			ShortcodeInfoProvider:   page.NopPage,
   59 			LanguageProvider:        s,
   60 			pagePages:               &pagePages{},
   61 
   62 			InternalDependencies: s,
   63 			init:                 lazy.New(),
   64 			m:                    metaProvider,
   65 			s:                    s,
   66 		},
   67 	}
   68 
   69 	ps.shortcodeState = newShortcodeHandler(ps, ps.s)
   70 
   71 	siteAdapter := pageSiteAdapter{s: s, p: ps}
   72 
   73 	ps.pageMenus = &pageMenus{p: ps}
   74 	ps.PageMenusProvider = ps.pageMenus
   75 	ps.GetPageProvider = siteAdapter
   76 	ps.GitInfoProvider = ps
   77 	ps.TranslationsProvider = ps
   78 	ps.ResourceDataProvider = &pageData{pageState: ps}
   79 	ps.RawContentProvider = ps
   80 	ps.ChildCareProvider = ps
   81 	ps.TreeProvider = pageTree{p: ps}
   82 	ps.Eqer = ps
   83 	ps.TranslationKeyProvider = ps
   84 	ps.ShortcodeInfoProvider = ps
   85 	ps.AlternativeOutputFormatsProvider = ps
   86 
   87 	return ps, nil
   88 }
   89 
   90 func newPageBucket(p *pageState) *pagesMapBucket {
   91 	return &pagesMapBucket{owner: p, pagesMapBucketPages: &pagesMapBucketPages{}}
   92 }
   93 
   94 func newPageFromMeta(
   95 	n *contentNode,
   96 	parentBucket *pagesMapBucket,
   97 	meta map[string]any,
   98 	metaProvider *pageMeta) (*pageState, error) {
   99 	if metaProvider.f == nil {
  100 		metaProvider.f = page.NewZeroFile(metaProvider.s.LogDistinct)
  101 	}
  102 
  103 	ps, err := newPageBase(metaProvider)
  104 	if err != nil {
  105 		return nil, err
  106 	}
  107 
  108 	bucket := parentBucket
  109 
  110 	if ps.IsNode() {
  111 		ps.bucket = newPageBucket(ps)
  112 	}
  113 
  114 	if meta != nil || parentBucket != nil {
  115 		if err := metaProvider.setMetadata(bucket, ps, meta); err != nil {
  116 			return nil, ps.wrapError(err)
  117 		}
  118 	}
  119 
  120 	if err := metaProvider.applyDefaultValues(n); err != nil {
  121 		return nil, err
  122 	}
  123 
  124 	ps.init.Add(func() (any, error) {
  125 		pp, err := newPagePaths(metaProvider.s, ps, metaProvider)
  126 		if err != nil {
  127 			return nil, err
  128 		}
  129 
  130 		makeOut := func(f output.Format, render bool) *pageOutput {
  131 			return newPageOutput(ps, pp, f, render)
  132 		}
  133 
  134 		shouldRenderPage := !ps.m.noRender()
  135 
  136 		if ps.m.standalone {
  137 			ps.pageOutput = makeOut(ps.m.outputFormats()[0], shouldRenderPage)
  138 		} else {
  139 			outputFormatsForPage := ps.m.outputFormats()
  140 
  141 			// Prepare output formats for all sites.
  142 			// We do this even if this page does not get rendered on
  143 			// its own. It may be referenced via .Site.GetPage and
  144 			// it will then need an output format.
  145 			ps.pageOutputs = make([]*pageOutput, len(ps.s.h.renderFormats))
  146 			created := make(map[string]*pageOutput)
  147 			for i, f := range ps.s.h.renderFormats {
  148 				po, found := created[f.Name]
  149 				if !found {
  150 					render := shouldRenderPage
  151 					if render {
  152 						_, render = outputFormatsForPage.GetByName(f.Name)
  153 					}
  154 					po = makeOut(f, render)
  155 					created[f.Name] = po
  156 				}
  157 				ps.pageOutputs[i] = po
  158 			}
  159 		}
  160 
  161 		if err := ps.initCommonProviders(pp); err != nil {
  162 			return nil, err
  163 		}
  164 
  165 		return nil, nil
  166 	})
  167 
  168 	return ps, err
  169 }
  170 
  171 // Used by the legacy 404, sitemap and robots.txt rendering
  172 func newPageStandalone(m *pageMeta, f output.Format) (*pageState, error) {
  173 	m.configuredOutputFormats = output.Formats{f}
  174 	m.standalone = true
  175 	p, err := newPageFromMeta(nil, nil, nil, m)
  176 	if err != nil {
  177 		return nil, err
  178 	}
  179 
  180 	if err := p.initPage(); err != nil {
  181 		return nil, err
  182 	}
  183 
  184 	return p, nil
  185 }
  186 
  187 type pageDeprecatedWarning struct {
  188 	p *pageState
  189 }
  190 
  191 func (p *pageDeprecatedWarning) IsDraft() bool          { return p.p.m.draft }
  192 func (p *pageDeprecatedWarning) Hugo() hugo.Info        { return p.p.s.Info.Hugo() }
  193 func (p *pageDeprecatedWarning) LanguagePrefix() string { return p.p.s.Info.LanguagePrefix }
  194 func (p *pageDeprecatedWarning) GetParam(key string) any {
  195 	return p.p.m.params[strings.ToLower(key)]
  196 }
  197 
  198 func (p *pageDeprecatedWarning) RSSLink() template.URL {
  199 	f := p.p.OutputFormats().Get("RSS")
  200 	if f == nil {
  201 		return ""
  202 	}
  203 	return template.URL(f.Permalink())
  204 }
  205 
  206 func (p *pageDeprecatedWarning) URL() string {
  207 	if p.p.IsPage() && p.p.m.urlPaths.URL != "" {
  208 		// This is the url set in front matter
  209 		return p.p.m.urlPaths.URL
  210 	}
  211 	// Fall back to the relative permalink.
  212 	return p.p.RelPermalink()
  213 }