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 }