github.com/neohugo/neohugo@v0.123.8/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/neohugo/neohugo/output"
    21  
    22  	"github.com/neohugo/neohugo/resources/kinds"
    23  	"github.com/neohugo/neohugo/resources/page"
    24  )
    25  
    26  func newPagePaths(ps *pageState) (pagePaths, error) {
    27  	s := ps.s
    28  	pm := ps.m
    29  
    30  	targetPathDescriptor, err := createTargetPathDescriptor(ps)
    31  	if err != nil {
    32  		return pagePaths{}, err
    33  	}
    34  
    35  	var outputFormats output.Formats
    36  
    37  	if ps.m.isStandalone() {
    38  		outputFormats = output.Formats{ps.m.standaloneOutputFormat}
    39  	} else {
    40  		outputFormats = pm.outputFormats()
    41  		if len(outputFormats) == 0 {
    42  			return pagePaths{}, nil
    43  		}
    44  
    45  		if pm.noRender() {
    46  			outputFormats = outputFormats[:1]
    47  		}
    48  	}
    49  
    50  	pageOutputFormats := make(page.OutputFormats, len(outputFormats))
    51  	targets := make(map[string]targetPathsHolder)
    52  
    53  	for i, f := range outputFormats {
    54  		desc := targetPathDescriptor
    55  		desc.Type = f
    56  		paths := page.CreateTargetPaths(desc)
    57  
    58  		var relPermalink, permalink string
    59  
    60  		// If a page is headless or bundled in another,
    61  		// it will not get published on its own and it will have no links.
    62  		// We also check the build options if it's set to not render or have
    63  		// a link.
    64  		if !pm.noLink() && !pm.bundled {
    65  			relPermalink = paths.RelPermalink(s.PathSpec)
    66  			permalink = paths.PermalinkForOutputFormat(s.PathSpec, f)
    67  		}
    68  
    69  		pageOutputFormats[i] = page.NewOutputFormat(relPermalink, permalink, len(outputFormats) == 1, f)
    70  
    71  		// Use the main format for permalinks, usually HTML.
    72  		permalinksIndex := 0
    73  		if f.Permalinkable {
    74  			// Unless it's permalinkable
    75  			permalinksIndex = i
    76  		}
    77  
    78  		targets[f.Name] = targetPathsHolder{
    79  			paths:        paths,
    80  			OutputFormat: pageOutputFormats[permalinksIndex],
    81  		}
    82  
    83  	}
    84  
    85  	var out page.OutputFormats
    86  	if !pm.noLink() {
    87  		out = pageOutputFormats
    88  	}
    89  
    90  	return pagePaths{
    91  		outputFormats:        out,
    92  		firstOutputFormat:    pageOutputFormats[0],
    93  		targetPaths:          targets,
    94  		targetPathDescriptor: targetPathDescriptor,
    95  	}, nil
    96  }
    97  
    98  type pagePaths struct {
    99  	outputFormats     page.OutputFormats
   100  	firstOutputFormat page.OutputFormat
   101  
   102  	targetPaths          map[string]targetPathsHolder
   103  	targetPathDescriptor page.TargetPathDescriptor
   104  }
   105  
   106  func (l pagePaths) OutputFormats() page.OutputFormats {
   107  	return l.outputFormats
   108  }
   109  
   110  func createTargetPathDescriptor(p *pageState) (page.TargetPathDescriptor, error) {
   111  	s := p.s
   112  	d := s.Deps
   113  	pm := p.m
   114  	alwaysInSubDir := p.Kind() == kinds.KindSitemap
   115  
   116  	pageInfoPage := p.PathInfo()
   117  	pageInfoCurrentSection := p.CurrentSection().PathInfo()
   118  	if p.s.Conf.DisablePathToLower() {
   119  		pageInfoPage = pageInfoPage.Unnormalized()
   120  		pageInfoCurrentSection = pageInfoCurrentSection.Unnormalized()
   121  	}
   122  
   123  	desc := page.TargetPathDescriptor{
   124  		PathSpec:    d.PathSpec,
   125  		Kind:        p.Kind(),
   126  		Path:        pageInfoPage,
   127  		Section:     pageInfoCurrentSection,
   128  		UglyURLs:    s.h.Conf.IsUglyURLs(p.Section()),
   129  		ForcePrefix: s.h.Conf.IsMultihost() || alwaysInSubDir,
   130  		URL:         pm.pageConfig.URL,
   131  	}
   132  
   133  	if pm.Slug() != "" {
   134  		desc.BaseName = pm.Slug()
   135  	} else if pm.isStandalone() && pm.standaloneOutputFormat.BaseName != "" {
   136  		desc.BaseName = pm.standaloneOutputFormat.BaseName
   137  	} else {
   138  		desc.BaseName = pageInfoPage.BaseNameNoIdentifier()
   139  	}
   140  
   141  	desc.PrefixFilePath = s.getLanguageTargetPathLang(alwaysInSubDir)
   142  	desc.PrefixLink = s.getLanguagePermalinkLang(alwaysInSubDir)
   143  
   144  	opath, err := d.ResourceSpec.Permalinks.Expand(p.Section(), p)
   145  	if err != nil {
   146  		return desc, err
   147  	}
   148  
   149  	if opath != "" {
   150  		opath, _ = url.QueryUnescape(opath)
   151  		if strings.HasSuffix(opath, "//") {
   152  			// When rewriting the _index of the section the permalink config is applied to,
   153  			// we get double slashes at the end sometimes; clear them up here
   154  			opath = strings.TrimSuffix(opath, "/")
   155  		}
   156  
   157  		desc.ExpandedPermalink = opath
   158  
   159  		if p.File() != nil {
   160  			s.Log.Debugf("Set expanded permalink path for %s %s to %#v", p.Kind(), p.File().Path(), opath)
   161  		} else {
   162  			s.Log.Debugf("Set expanded permalink path for %s in %v to %#v", p.Kind(), desc.Section.Path(), opath)
   163  		}
   164  	}
   165  
   166  	return desc, nil
   167  }