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 }