-
Notifications
You must be signed in to change notification settings - Fork 2
Expand file tree
/
Copy pathtemplate_render.go
More file actions
111 lines (94 loc) · 3.68 KB
/
Copy pathtemplate_render.go
File metadata and controls
111 lines (94 loc) · 3.68 KB
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
package vuego
import (
"bytes"
"context"
"fmt"
"io"
"golang.org/x/net/html"
"github.com/titpetric/vuego/internal/helpers"
)
// Render processes the loaded template and writes the output to w.
// If the template contains a "layout" key in its front matter, it will load and render
// the specified layout. Layouts can be chained, so one layout can trigger another layout.
// If no layout is specified on the first template, defaults to layouts/base.vuego if available.
// Layout paths are resolved relative to the current template first, then fall back to layouts/.
// Requires that Load() has been called first.
func (t *template) Render(ctx context.Context, w io.Writer) error {
// Check if context is already cancelled before starting
if err := ctx.Err(); err != nil {
return err
}
if err := t.Err(); err != nil {
return err
}
if !t.filenameLoaded {
return fmt.Errorf("no template loaded; call Load() first")
}
// Check if layout is specified in front matter
layout := t.Get("layout")
if layout != "" {
// Layout is specified, use layout rendering
return t.layout(ctx, w)
}
// No layout specified, render without layout
return t.renderWithoutLayout(ctx, w)
}
// renderWithoutLayout renders the template without checking for layouts.
// Used internally by the layout chain to avoid infinite recursion.
func (t *template) renderWithoutLayout(ctx context.Context, w io.Writer) error {
// Check if context is already cancelled before starting
if err := ctx.Err(); err != nil {
return err
}
return t.vue.Render(ctx, w, t.filename, t.stack.EnvMap())
}
// RenderFile processes the template file and writes the output to w.
// Uses internal buffering so w is unmodified if an error occurs.
// The context can be used to cancel the rendering operation.
func (t *template) RenderFile(ctx context.Context, w io.Writer, filename string) error {
return t.Load(filename).Render(ctx, w)
}
// RenderString processes a template string and writes the output to w.
// Uses internal buffering so w is unmodified if an error occurs.
// The context can be used to cancel the rendering operation.
func (t *template) RenderString(ctx context.Context, w io.Writer, templateStr string) error {
return t.RenderByte(ctx, w, []byte(templateStr))
}
// RenderByte processes template bytes and writes the output to w.
// Uses internal buffering so w is unmodified if an error occurs.
// The context can be used to cancel the rendering operation.
func (t *template) RenderByte(ctx context.Context, w io.Writer, templateData []byte) error {
return t.RenderReader(ctx, w, bytes.NewReader(templateData))
}
// RenderReader processes template data from a reader and writes the output to w.
// Uses internal buffering so w is unmodified if an error occurs.
// The context can be used to cancel the rendering operation.
func (t *template) RenderReader(ctx context.Context, w io.Writer, r io.Reader) error {
// Check if context is already cancelled before starting
if err := ctx.Err(); err != nil {
return err
}
// Parse the template from reader as a fragment
body := helpers.GetBodyNode()
dom, err := html.ParseFragment(r, body)
if err != nil {
return fmt.Errorf("error parsing template: %w", err)
}
// Create VueContext with filename from loaded template
vueCtx := NewVueContext(ctx, t.filename, &VueContextOptions{
Stack: t.stack.Copy(),
Processors: t.vue.nodeProcessors,
})
// Buffer the output to ensure w is unmodified on error
buf := &bytes.Buffer{}
if err := t.vue.renderNodesWithContext(vueCtx, buf, dom); err != nil {
return err
}
// Check context cancellation before writing
if err := ctx.Err(); err != nil {
return err
}
// Only write to w if rendering succeeded
_, err = buf.WriteTo(w)
return err
}