github.com/kovansky/hugo@v0.92.3-0.20220224232819-63076e4ff19f/hugolib/page__paths.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  	"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  }