github.com/gohugoio/hugo@v0.88.1/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 }