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