page__paths.go (4400B)
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 "net/url" 18 "strings" 19 20 "github.com/gohugoio/hugo/helpers" 21 22 "github.com/gohugoio/hugo/resources/page" 23 ) 24 25 func newPagePaths( 26 s *Site, 27 p page.Page, 28 pm *pageMeta) (pagePaths, error) { 29 targetPathDescriptor, err := createTargetPathDescriptor(s, p, pm) 30 if err != nil { 31 return pagePaths{}, err 32 } 33 34 outputFormats := pm.outputFormats() 35 if len(outputFormats) == 0 { 36 return pagePaths{}, nil 37 } 38 39 if pm.noRender() { 40 outputFormats = outputFormats[:1] 41 } 42 43 pageOutputFormats := make(page.OutputFormats, len(outputFormats)) 44 targets := make(map[string]targetPathsHolder) 45 46 for i, f := range outputFormats { 47 desc := targetPathDescriptor 48 desc.Type = f 49 paths := page.CreateTargetPaths(desc) 50 51 var relPermalink, permalink string 52 53 // If a page is headless or bundled in another, 54 // it will not get published on its own and it will have no links. 55 // We also check the build options if it's set to not render or have 56 // a link. 57 if !pm.noLink() && !pm.bundled { 58 relPermalink = paths.RelPermalink(s.PathSpec) 59 permalink = paths.PermalinkForOutputFormat(s.PathSpec, f) 60 } 61 62 pageOutputFormats[i] = page.NewOutputFormat(relPermalink, permalink, len(outputFormats) == 1, f) 63 64 // Use the main format for permalinks, usually HTML. 65 permalinksIndex := 0 66 if f.Permalinkable { 67 // Unless it's permalinkable 68 permalinksIndex = i 69 } 70 71 targets[f.Name] = targetPathsHolder{ 72 paths: paths, 73 OutputFormat: pageOutputFormats[permalinksIndex], 74 } 75 76 } 77 78 var out page.OutputFormats 79 if !pm.noLink() { 80 out = pageOutputFormats 81 } 82 83 return pagePaths{ 84 outputFormats: out, 85 firstOutputFormat: pageOutputFormats[0], 86 targetPaths: targets, 87 targetPathDescriptor: targetPathDescriptor, 88 }, nil 89 } 90 91 type pagePaths struct { 92 outputFormats page.OutputFormats 93 firstOutputFormat page.OutputFormat 94 95 targetPaths map[string]targetPathsHolder 96 targetPathDescriptor page.TargetPathDescriptor 97 } 98 99 func (l pagePaths) OutputFormats() page.OutputFormats { 100 return l.outputFormats 101 } 102 103 func createTargetPathDescriptor(s *Site, p page.Page, pm *pageMeta) (page.TargetPathDescriptor, error) { 104 var ( 105 dir string 106 baseName string 107 contentBaseName string 108 ) 109 110 d := s.Deps 111 112 if !p.File().IsZero() { 113 dir = p.File().Dir() 114 baseName = p.File().TranslationBaseName() 115 contentBaseName = p.File().ContentBaseName() 116 } 117 118 if baseName != contentBaseName { 119 // See https://github.com/gohugoio/hugo/issues/4870 120 // A leaf bundle 121 dir = strings.TrimSuffix(dir, contentBaseName+helpers.FilePathSeparator) 122 baseName = contentBaseName 123 } 124 125 alwaysInSubDir := p.Kind() == kindSitemap 126 127 desc := page.TargetPathDescriptor{ 128 PathSpec: d.PathSpec, 129 Kind: p.Kind(), 130 Sections: p.SectionsEntries(), 131 UglyURLs: s.Info.uglyURLs(p), 132 ForcePrefix: s.h.IsMultihost() || alwaysInSubDir, 133 Dir: dir, 134 URL: pm.urlPaths.URL, 135 } 136 137 if pm.Slug() != "" { 138 desc.BaseName = pm.Slug() 139 } else { 140 desc.BaseName = baseName 141 } 142 143 desc.PrefixFilePath = s.getLanguageTargetPathLang(alwaysInSubDir) 144 desc.PrefixLink = s.getLanguagePermalinkLang(alwaysInSubDir) 145 146 // Expand only page.KindPage and page.KindTaxonomy; don't expand other Kinds of Pages 147 // like page.KindSection or page.KindTaxonomyTerm because they are "shallower" and 148 // the permalink configuration values are likely to be redundant, e.g. 149 // naively expanding /category/:slug/ would give /category/categories/ for 150 // the "categories" page.KindTaxonomyTerm. 151 if p.Kind() == page.KindPage || p.Kind() == page.KindTerm { 152 opath, err := d.ResourceSpec.Permalinks.Expand(p.Section(), p) 153 if err != nil { 154 return desc, err 155 } 156 157 if opath != "" { 158 opath, _ = url.QueryUnescape(opath) 159 desc.ExpandedPermalink = opath 160 } 161 162 } 163 164 return desc, nil 165 }