-
Notifications
You must be signed in to change notification settings - Fork 0
/
pagecontentoutput.go
147 lines (116 loc) · 3.15 KB
/
pagecontentoutput.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
package entity
import (
"context"
"fmt"
"github.com/gohugonet/hugoverse/internal/domain/contenthub"
"github.com/gohugonet/hugoverse/internal/domain/markdown"
"github.com/gohugonet/hugoverse/pkg/lazy"
"html/template"
"runtime/debug"
"strings"
"sync"
"time"
)
func newPageContentOutput(p *pageState) (*pageContentOutput, error) {
parent := p.init
cp := &pageContentOutput{
p: p,
renderHooks: &renderHooks{},
}
initContent := func() (err error) {
if p.cmap == nil {
// Nothing to do.
return nil
}
defer func() {
// See https://github.com/gohugonet/hugoverse/pkgissues/6210
if r := recover(); r != nil {
err = fmt.Errorf("%s", r)
fmt.Printf("[BUG] Got panic:\n%s\n%s", r, string(debug.Stack()))
}
}()
cp.workContent = p.contentToRender(p.source.parsed, p.cmap)
r, err := cp.renderContent(cp.workContent, true)
if err != nil {
return err
}
cp.workContent = r.Bytes()
cp.content = BytesToHTML(cp.workContent)
return nil
}
// There may be recursive loops in shortcodes and render hooks.
cp.initMain = parent.BranchWithTimeout(30*time.Second, func(ctx context.Context) (any, error) {
return nil, initContent()
})
cp.initPlain = cp.initMain.Branch(func() (any, error) {
cp.plain = string(cp.content)
cp.plainWords = strings.Fields(cp.plain)
return nil, nil
})
return cp, nil
}
// BytesToHTML converts bytes to type template.HTML.
func BytesToHTML(b []byte) template.HTML {
return template.HTML(string(b))
}
// pageContentOutput represents the Page content for a given output format.
type pageContentOutput struct {
p *pageState
// Lazy load dependencies
initMain *lazy.Init
initPlain *lazy.Init
workContent []byte
// Content sections
content template.HTML
summary template.HTML
plainWords []string
plain string
// Renders Markdown hooks.
renderHooks *renderHooks
}
type renderHooks struct {
getRenderer markdown.GetRendererFunc
init sync.Once
}
func (cp *pageContentOutput) renderContent(content []byte, renderTOC bool) (contenthub.Result, error) {
if err := cp.initRenderHooks(); err != nil {
return nil, err
}
c := cp.p.getContentConverter()
return cp.renderContentWithConverter(c, content, renderTOC)
}
func (cp *pageContentOutput) initRenderHooks() error {
if cp == nil {
return nil
}
cp.renderHooks.init.Do(func() {
// TODO, no template based rendering, use markdown default render
cp.renderHooks.getRenderer = markdown.DefaultRendererFunc
})
return nil
}
func (cp *pageContentOutput) renderContentWithConverter(
c contenthub.Converter, content []byte, renderTOC bool) (contenthub.Result, error) {
fmt.Println("renderContentWithConverter", string(content), renderTOC)
r, err := c.Convert(
markdown.RenderContext{
Ctx: context.Background(),
Src: content,
RenderTOC: renderTOC,
GetRenderer: cp.renderHooks.getRenderer,
})
return r, err
}
func (cp *pageContentOutput) Content() (any, error) {
if cp.initInit(cp.initMain) {
return cp.content, nil
}
return nil, nil
}
func (cp *pageContentOutput) initInit(init *lazy.Init) bool {
_, err := init.Do()
if err != nil {
fmt.Printf("fatal error %v", err)
}
return err == nil
}