github.com/kovansky/hugo@v0.92.3-0.20220224232819-63076e4ff19f/hugolib/page__content.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  	"fmt"
    18  
    19  	"github.com/gohugoio/hugo/output"
    20  	"github.com/gohugoio/hugo/parser/pageparser"
    21  )
    22  
    23  var (
    24  	internalSummaryDividerBase      = "HUGOMORE42"
    25  	internalSummaryDividerBaseBytes = []byte(internalSummaryDividerBase)
    26  	internalSummaryDividerPre       = []byte("\n\n" + internalSummaryDividerBase + "\n\n")
    27  )
    28  
    29  // The content related items on a Page.
    30  type pageContent struct {
    31  	selfLayout string
    32  	truncated  bool
    33  
    34  	cmap *pageContentMap
    35  
    36  	shortcodeState *shortcodeHandler
    37  
    38  	source rawPageContent
    39  }
    40  
    41  // returns the content to be processed by Blackfriday or similar.
    42  func (p pageContent) contentToRender(renderedShortcodes map[string]string) []byte {
    43  	source := p.source.parsed.Input()
    44  
    45  	c := make([]byte, 0, len(source)+(len(source)/10))
    46  
    47  	for _, it := range p.cmap.items {
    48  		switch v := it.(type) {
    49  		case pageparser.Item:
    50  			c = append(c, source[v.Pos:v.Pos+len(v.Val)]...)
    51  		case pageContentReplacement:
    52  			c = append(c, v.val...)
    53  		case *shortcode:
    54  			if !v.insertPlaceholder() {
    55  				// Insert the rendered shortcode.
    56  				renderedShortcode, found := renderedShortcodes[v.placeholder]
    57  				if !found {
    58  					// This should never happen.
    59  					panic(fmt.Sprintf("rendered shortcode %q not found", v.placeholder))
    60  				}
    61  
    62  				c = append(c, []byte(renderedShortcode)...)
    63  
    64  			} else {
    65  				// Insert the placeholder so we can insert the content after
    66  				// markdown processing.
    67  				c = append(c, []byte(v.placeholder)...)
    68  			}
    69  		default:
    70  			panic(fmt.Sprintf("unknown item type %T", it))
    71  		}
    72  	}
    73  
    74  	return c
    75  }
    76  
    77  func (p pageContent) selfLayoutForOutput(f output.Format) string {
    78  	if p.selfLayout == "" {
    79  		return ""
    80  	}
    81  	return p.selfLayout + f.Name
    82  }
    83  
    84  type rawPageContent struct {
    85  	hasSummaryDivider bool
    86  
    87  	// The AST of the parsed page. Contains information about:
    88  	// shortcodes, front matter, summary indicators.
    89  	parsed pageparser.Result
    90  
    91  	// Returns the position in bytes after any front matter.
    92  	posMainContent int
    93  
    94  	// These are set if we're able to determine this from the source.
    95  	posSummaryEnd int
    96  	posBodyStart  int
    97  }
    98  
    99  type pageContentReplacement struct {
   100  	val []byte
   101  
   102  	source pageparser.Item
   103  }
   104  
   105  type pageContentMap struct {
   106  
   107  	// If not, we can skip any pre-rendering of shortcodes.
   108  	hasMarkdownShortcode bool
   109  
   110  	// Indicates whether we must do placeholder replacements.
   111  	hasNonMarkdownShortcode bool
   112  
   113  	//  *shortcode, pageContentReplacement or pageparser.Item
   114  	items []interface{}
   115  }
   116  
   117  func (p *pageContentMap) AddBytes(item pageparser.Item) {
   118  	p.items = append(p.items, item)
   119  }
   120  
   121  func (p *pageContentMap) AddReplacement(val []byte, source pageparser.Item) {
   122  	p.items = append(p.items, pageContentReplacement{val: val, source: source})
   123  }
   124  
   125  func (p *pageContentMap) AddShortcode(s *shortcode) {
   126  	p.items = append(p.items, s)
   127  	if s.insertPlaceholder() {
   128  		p.hasNonMarkdownShortcode = true
   129  	} else {
   130  		p.hasMarkdownShortcode = true
   131  	}
   132  }