github.com/graemephi/kahugo@v0.62.3-0.20211121071557-d78c0423784d/hugolib/page__new.go (about)

     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  	"github.com/gohugoio/hugo/common/hugo"
    21  
    22  	"github.com/gohugoio/hugo/common/maps"
    23  	"github.com/gohugoio/hugo/source"
    24  
    25  	"github.com/gohugoio/hugo/output"
    26  
    27  	"github.com/gohugoio/hugo/lazy"
    28  
    29  	"github.com/gohugoio/hugo/resources/page"
    30  )
    31  
    32  func newPageBase(metaProvider *pageMeta) (*pageState, error) {
    33  	if metaProvider.s == nil {
    34  		panic("must provide a Site")
    35  	}
    36  
    37  	s := metaProvider.s
    38  
    39  	ps := &pageState{
    40  		pageOutput: nopPageOutput,
    41  		pageCommon: &pageCommon{
    42  			FileProvider:            metaProvider,
    43  			AuthorProvider:          metaProvider,
    44  			Scratcher:               maps.NewScratcher(),
    45  			Positioner:              page.NopPage,
    46  			InSectionPositioner:     page.NopPage,
    47  			ResourceMetaProvider:    metaProvider,
    48  			ResourceParamsProvider:  metaProvider,
    49  			PageMetaProvider:        metaProvider,
    50  			RelatedKeywordsProvider: metaProvider,
    51  			OutputFormatsProvider:   page.NopPage,
    52  			ResourceTypeProvider:    pageTypesProvider,
    53  			MediaTypeProvider:       pageTypesProvider,
    54  			RefProvider:             page.NopPage,
    55  			ShortcodeInfoProvider:   page.NopPage,
    56  			LanguageProvider:        s,
    57  			pagePages:               &pagePages{},
    58  
    59  			InternalDependencies: s,
    60  			init:                 lazy.New(),
    61  			m:                    metaProvider,
    62  			s:                    s,
    63  		},
    64  	}
    65  
    66  	siteAdapter := pageSiteAdapter{s: s, p: ps}
    67  
    68  	deprecatedWarningPage := struct {
    69  		source.FileWithoutOverlap
    70  		page.DeprecatedWarningPageMethods1
    71  	}{
    72  		FileWithoutOverlap:            metaProvider.File(),
    73  		DeprecatedWarningPageMethods1: &pageDeprecatedWarning{p: ps},
    74  	}
    75  
    76  	ps.DeprecatedWarningPageMethods = page.NewDeprecatedWarningPage(deprecatedWarningPage)
    77  	ps.pageMenus = &pageMenus{p: ps}
    78  	ps.PageMenusProvider = ps.pageMenus
    79  	ps.GetPageProvider = siteAdapter
    80  	ps.GitInfoProvider = ps
    81  	ps.TranslationsProvider = ps
    82  	ps.ResourceDataProvider = &pageData{pageState: ps}
    83  	ps.RawContentProvider = ps
    84  	ps.ChildCareProvider = ps
    85  	ps.TreeProvider = pageTree{p: ps}
    86  	ps.Eqer = ps
    87  	ps.TranslationKeyProvider = ps
    88  	ps.ShortcodeInfoProvider = ps
    89  	ps.PageRenderProvider = ps
    90  	ps.AlternativeOutputFormatsProvider = ps
    91  
    92  	return ps, nil
    93  }
    94  
    95  func newPageBucket(p *pageState) *pagesMapBucket {
    96  	return &pagesMapBucket{owner: p, pagesMapBucketPages: &pagesMapBucketPages{}}
    97  }
    98  
    99  func newPageFromMeta(
   100  	n *contentNode,
   101  	parentBucket *pagesMapBucket,
   102  	meta map[string]interface{},
   103  	metaProvider *pageMeta) (*pageState, error) {
   104  	if metaProvider.f == nil {
   105  		metaProvider.f = page.NewZeroFile(metaProvider.s.LogDistinct)
   106  	}
   107  
   108  	ps, err := newPageBase(metaProvider)
   109  	if err != nil {
   110  		return nil, err
   111  	}
   112  
   113  	bucket := parentBucket
   114  
   115  	if ps.IsNode() {
   116  		ps.bucket = newPageBucket(ps)
   117  	}
   118  
   119  	if meta != nil || parentBucket != nil {
   120  		if err := metaProvider.setMetadata(bucket, ps, meta); err != nil {
   121  			return nil, ps.wrapError(err)
   122  		}
   123  	}
   124  
   125  	if err := metaProvider.applyDefaultValues(n); err != nil {
   126  		return nil, err
   127  	}
   128  
   129  	ps.init.Add(func() (interface{}, error) {
   130  		pp, err := newPagePaths(metaProvider.s, ps, metaProvider)
   131  		if err != nil {
   132  			return nil, err
   133  		}
   134  
   135  		makeOut := func(f output.Format, render bool) *pageOutput {
   136  			return newPageOutput(ps, pp, f, render)
   137  		}
   138  
   139  		shouldRenderPage := !ps.m.noRender()
   140  
   141  		if ps.m.standalone {
   142  			ps.pageOutput = makeOut(ps.m.outputFormats()[0], shouldRenderPage)
   143  		} else {
   144  			outputFormatsForPage := ps.m.outputFormats()
   145  
   146  			// Prepare output formats for all sites.
   147  			// We do this even if this page does not get rendered on
   148  			// its own. It may be referenced via .Site.GetPage and
   149  			// it will then need an output format.
   150  			ps.pageOutputs = make([]*pageOutput, len(ps.s.h.renderFormats))
   151  			created := make(map[string]*pageOutput)
   152  			for i, f := range ps.s.h.renderFormats {
   153  				po, found := created[f.Name]
   154  				if !found {
   155  					render := shouldRenderPage
   156  					if render {
   157  						_, render = outputFormatsForPage.GetByName(f.Name)
   158  					}
   159  					po = makeOut(f, render)
   160  					created[f.Name] = po
   161  				}
   162  				ps.pageOutputs[i] = po
   163  			}
   164  		}
   165  
   166  		if err := ps.initCommonProviders(pp); err != nil {
   167  			return nil, err
   168  		}
   169  
   170  		return nil, nil
   171  	})
   172  
   173  	return ps, err
   174  }
   175  
   176  // Used by the legacy 404, sitemap and robots.txt rendering
   177  func newPageStandalone(m *pageMeta, f output.Format) (*pageState, error) {
   178  	m.configuredOutputFormats = output.Formats{f}
   179  	m.standalone = true
   180  	p, err := newPageFromMeta(nil, nil, nil, m)
   181  	if err != nil {
   182  		return nil, err
   183  	}
   184  
   185  	if err := p.initPage(); err != nil {
   186  		return nil, err
   187  	}
   188  
   189  	return p, nil
   190  }
   191  
   192  type pageDeprecatedWarning struct {
   193  	p *pageState
   194  }
   195  
   196  func (p *pageDeprecatedWarning) IsDraft() bool          { return p.p.m.draft }
   197  func (p *pageDeprecatedWarning) Hugo() hugo.Info        { return p.p.s.Info.Hugo() }
   198  func (p *pageDeprecatedWarning) LanguagePrefix() string { return p.p.s.Info.LanguagePrefix }
   199  func (p *pageDeprecatedWarning) GetParam(key string) interface{} {
   200  	return p.p.m.params[strings.ToLower(key)]
   201  }
   202  
   203  func (p *pageDeprecatedWarning) RSSLink() template.URL {
   204  	f := p.p.OutputFormats().Get("RSS")
   205  	if f == nil {
   206  		return ""
   207  	}
   208  	return template.URL(f.Permalink())
   209  }
   210  
   211  func (p *pageDeprecatedWarning) URL() string {
   212  	if p.p.IsPage() && p.p.m.urlPaths.URL != "" {
   213  		// This is the url set in front matter
   214  		return p.p.m.urlPaths.URL
   215  	}
   216  	// Fall back to the relative permalink.
   217  	return p.p.RelPermalink()
   218  }