github.com/graemephi/kahugo@v0.62.3-0.20211121071557-d78c0423784d/hugolib/page__output.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  	"github.com/gohugoio/hugo/markup/converter"
    18  	"github.com/gohugoio/hugo/output"
    19  	"github.com/gohugoio/hugo/resources/page"
    20  	"github.com/gohugoio/hugo/resources/resource"
    21  )
    22  
    23  func newPageOutput(
    24  	ps *pageState,
    25  	pp pagePaths,
    26  	f output.Format,
    27  	render bool) *pageOutput {
    28  	var targetPathsProvider targetPathsHolder
    29  	var linksProvider resource.ResourceLinksProvider
    30  
    31  	ft, found := pp.targetPaths[f.Name]
    32  	if !found {
    33  		// Link to the main output format
    34  		ft = pp.targetPaths[pp.firstOutputFormat.Format.Name]
    35  	}
    36  	targetPathsProvider = ft
    37  	linksProvider = ft
    38  
    39  	var paginatorProvider page.PaginatorProvider = page.NopPage
    40  	var pag *pagePaginator
    41  
    42  	if render && ps.IsNode() {
    43  		pag = newPagePaginator(ps)
    44  		paginatorProvider = pag
    45  	}
    46  
    47  	providers := struct {
    48  		page.PaginatorProvider
    49  		resource.ResourceLinksProvider
    50  		targetPather
    51  	}{
    52  		paginatorProvider,
    53  		linksProvider,
    54  		targetPathsProvider,
    55  	}
    56  
    57  	po := &pageOutput{
    58  		f:                       f,
    59  		pagePerOutputProviders:  providers,
    60  		ContentProvider:         page.NopPage,
    61  		TableOfContentsProvider: page.NopPage,
    62  		render:                  render,
    63  		paginator:               pag,
    64  	}
    65  
    66  	return po
    67  }
    68  
    69  // We create a pageOutput for every output format combination, even if this
    70  // particular page isn't configured to be rendered to that format.
    71  type pageOutput struct {
    72  	// Set if this page isn't configured to be rendered to this format.
    73  	render bool
    74  
    75  	f output.Format
    76  
    77  	// Only set if render is set.
    78  	// Note that this will be lazily initialized, so only used if actually
    79  	// used in template(s).
    80  	paginator *pagePaginator
    81  
    82  	// These interface provides the functionality that is specific for this
    83  	// output format.
    84  	pagePerOutputProviders
    85  	page.ContentProvider
    86  	page.TableOfContentsProvider
    87  
    88  	// May be nil.
    89  	cp *pageContentOutput
    90  }
    91  
    92  func (o *pageOutput) initRenderHooks() error {
    93  	if o.cp == nil {
    94  		return nil
    95  	}
    96  
    97  	var initErr error
    98  
    99  	o.cp.renderHooks.init.Do(func() {
   100  		ps := o.cp.p
   101  
   102  		c := ps.getContentConverter()
   103  		if c == nil || !c.Supports(converter.FeatureRenderHooks) {
   104  			return
   105  		}
   106  
   107  		h, err := ps.createRenderHooks(o.f)
   108  		if err != nil {
   109  			initErr = err
   110  			return
   111  		}
   112  		o.cp.renderHooks.hooks = h
   113  
   114  		if !o.cp.renderHooksHaveVariants || h.IsZero() {
   115  			// Check if there is a different render hooks template
   116  			// for any of the other page output formats.
   117  			// If not, we can reuse this.
   118  			for _, po := range ps.pageOutputs {
   119  				if po.f.Name != o.f.Name {
   120  					h2, err := ps.createRenderHooks(po.f)
   121  					if err != nil {
   122  						initErr = err
   123  						return
   124  					}
   125  
   126  					if h2.IsZero() {
   127  						continue
   128  					}
   129  
   130  					if o.cp.renderHooks.hooks.IsZero() {
   131  						o.cp.renderHooks.hooks = h2
   132  					}
   133  
   134  					o.cp.renderHooksHaveVariants = !h2.Eq(o.cp.renderHooks.hooks)
   135  
   136  					if o.cp.renderHooksHaveVariants {
   137  						break
   138  					}
   139  
   140  				}
   141  			}
   142  		}
   143  	})
   144  
   145  	return initErr
   146  }
   147  
   148  func (p *pageOutput) initContentProvider(cp *pageContentOutput) {
   149  	if cp == nil {
   150  		return
   151  	}
   152  	p.ContentProvider = cp
   153  	p.TableOfContentsProvider = cp
   154  	p.cp = cp
   155  }
   156  
   157  func (p *pageOutput) enablePlaceholders() {
   158  	if p.cp != nil {
   159  		p.cp.enablePlaceholders()
   160  	}
   161  }