github.com/linchen2chris/hugo@v0.0.0-20230307053224-cec209389705/resources/page/page_lazy_contentprovider.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 page 15 16 import ( 17 "context" 18 "html/template" 19 20 "github.com/gohugoio/hugo/lazy" 21 "github.com/gohugoio/hugo/markup/converter" 22 "github.com/gohugoio/hugo/markup/tableofcontents" 23 ) 24 25 // OutputFormatContentProvider represents the method set that is "outputFormat aware" and that we 26 // provide lazy initialization for in case they get invoked outside of their normal rendering context, e.g. via .Translations. 27 // Note that this set is currently not complete, but should cover the most common use cases. 28 // For the others, the implementation will be from the page.NoopPage. 29 type OutputFormatContentProvider interface { 30 OutputFormatPageContentProvider 31 32 // for internal use. 33 ContentRenderer 34 } 35 36 // OutputFormatPageContentProvider holds the exported methods from Page that are "outputFormat aware". 37 type OutputFormatPageContentProvider interface { 38 ContentProvider 39 TableOfContentsProvider 40 PageRenderProvider 41 } 42 43 // LazyContentProvider initializes itself when read. Each method of the 44 // ContentProvider interface initializes a content provider and shares it 45 // with other methods. 46 // 47 // Used in cases where we cannot guarantee whether the content provider 48 // will be needed. Must create via NewLazyContentProvider. 49 type LazyContentProvider struct { 50 init *lazy.Init 51 cp OutputFormatContentProvider 52 } 53 54 // NewLazyContentProvider returns a LazyContentProvider initialized with 55 // function f. The resulting LazyContentProvider calls f in order to 56 // retrieve a ContentProvider 57 func NewLazyContentProvider(f func() (OutputFormatContentProvider, error)) *LazyContentProvider { 58 lcp := LazyContentProvider{ 59 init: lazy.New(), 60 cp: NopCPageContentRenderer, 61 } 62 lcp.init.Add(func(context.Context) (any, error) { 63 cp, err := f() 64 if err != nil { 65 return nil, err 66 } 67 lcp.cp = cp 68 return nil, nil 69 }) 70 return &lcp 71 } 72 73 func (lcp *LazyContentProvider) Reset() { 74 lcp.init.Reset() 75 } 76 77 func (lcp *LazyContentProvider) TableOfContents(ctx context.Context) template.HTML { 78 lcp.init.Do(ctx) 79 return lcp.cp.TableOfContents(ctx) 80 81 } 82 83 func (lcp *LazyContentProvider) Fragments(ctx context.Context) *tableofcontents.Fragments { 84 lcp.init.Do(ctx) 85 return lcp.cp.Fragments(ctx) 86 } 87 88 func (lcp *LazyContentProvider) Content(ctx context.Context) (any, error) { 89 lcp.init.Do(ctx) 90 return lcp.cp.Content(ctx) 91 } 92 93 func (lcp *LazyContentProvider) Plain(ctx context.Context) string { 94 lcp.init.Do(ctx) 95 return lcp.cp.Plain(ctx) 96 } 97 98 func (lcp *LazyContentProvider) PlainWords(ctx context.Context) []string { 99 lcp.init.Do(ctx) 100 return lcp.cp.PlainWords(ctx) 101 } 102 103 func (lcp *LazyContentProvider) Summary(ctx context.Context) template.HTML { 104 lcp.init.Do(ctx) 105 return lcp.cp.Summary(ctx) 106 } 107 108 func (lcp *LazyContentProvider) Truncated(ctx context.Context) bool { 109 lcp.init.Do(ctx) 110 return lcp.cp.Truncated(ctx) 111 } 112 113 func (lcp *LazyContentProvider) FuzzyWordCount(ctx context.Context) int { 114 lcp.init.Do(ctx) 115 return lcp.cp.FuzzyWordCount(ctx) 116 } 117 118 func (lcp *LazyContentProvider) WordCount(ctx context.Context) int { 119 lcp.init.Do(ctx) 120 return lcp.cp.WordCount(ctx) 121 } 122 123 func (lcp *LazyContentProvider) ReadingTime(ctx context.Context) int { 124 lcp.init.Do(ctx) 125 return lcp.cp.ReadingTime(ctx) 126 } 127 128 func (lcp *LazyContentProvider) Len(ctx context.Context) int { 129 lcp.init.Do(ctx) 130 return lcp.cp.Len(ctx) 131 } 132 133 func (lcp *LazyContentProvider) Render(ctx context.Context, layout ...string) (template.HTML, error) { 134 lcp.init.Do(context.TODO()) 135 return lcp.cp.Render(ctx, layout...) 136 } 137 138 func (lcp *LazyContentProvider) RenderString(ctx context.Context, args ...any) (template.HTML, error) { 139 lcp.init.Do(ctx) 140 return lcp.cp.RenderString(ctx, args...) 141 } 142 143 func (lcp *LazyContentProvider) ParseAndRenderContent(ctx context.Context, content []byte, renderTOC bool) (converter.ResultRender, error) { 144 lcp.init.Do(ctx) 145 return lcp.cp.ParseAndRenderContent(ctx, content, renderTOC) 146 } 147 148 func (lcp *LazyContentProvider) ParseContent(ctx context.Context, content []byte) (converter.ResultParse, bool, error) { 149 lcp.init.Do(ctx) 150 return lcp.cp.ParseContent(ctx, content) 151 } 152 func (lcp *LazyContentProvider) RenderContent(ctx context.Context, content []byte, doc any) (converter.ResultRender, bool, error) { 153 lcp.init.Do(ctx) 154 return lcp.cp.RenderContent(ctx, content, doc) 155 }