-
Notifications
You must be signed in to change notification settings - Fork 2
Expand file tree
/
Copy pathloader.go
More file actions
99 lines (83 loc) · 2.8 KB
/
Copy pathloader.go
File metadata and controls
99 lines (83 loc) · 2.8 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
package vuego
import (
"bytes"
"fmt"
"io/fs"
"golang.org/x/net/html"
yaml "gopkg.in/yaml.v3"
"github.com/titpetric/vuego/internal/parser"
)
// Loader loads and parses .vuego files from an fs.FS.
type Loader struct {
// FS is the file system used to load templates.
FS fs.FS
}
// NewLoader creates a Loader backed by fs.
func NewLoader(fs fs.FS) *Loader {
return &Loader{
FS: fs,
}
}
// Stat checks that filename exists in the loader filesystem.
func (l *Loader) Stat(filename string) error {
_, err := fs.Stat(l.FS, filename)
return err
}
// Load parses a full HTML document from the given filename.
func (l *Loader) Load(filename string) ([]*html.Node, error) {
return l.LoadFragment(filename)
}
// extractFrontMatter extracts YAML front-matter from a template if it starts with ---.
// Returns the front-matter data as map[string]any and the remaining template content.
// If no front-matter is present, returns nil map and the original content.
func extractFrontMatter(content []byte) (map[string]any, []byte, error) {
// Check if content starts with ---
if !bytes.HasPrefix(content, []byte("---")) {
return nil, content, nil
}
// Find the closing --- delimiter
rest := content[3:]
delimIdx := bytes.Index(rest, []byte("\n---"))
if delimIdx == -1 {
// No closing delimiter found
return nil, content, nil
}
// Extract front-matter YAML (between the delimiters)
frontMatterBytes := rest[:delimIdx]
remainingContent := rest[delimIdx+4:] // Skip "\n---"
// Skip optional newline after closing ---
if len(remainingContent) > 0 && remainingContent[0] == '\n' {
remainingContent = remainingContent[1:]
}
// Parse YAML
data := make(map[string]any)
if err := yaml.Unmarshal(frontMatterBytes, &data); err != nil {
return nil, nil, fmt.Errorf("error parsing front-matter YAML: %w", err)
}
return data, remainingContent, nil
}
// LoadFragment parses a template fragment; if the file is a full document, it falls back to Load.
// Front-matter is extracted and discarded; use loadFragment to access it.
func (l *Loader) LoadFragment(filename string) ([]*html.Node, error) {
_, templateBytes, err := l.loadFragment(filename)
if err != nil {
return nil, err
}
return parser.ParseTemplateBytes(templateBytes)
}
// loadFragment loads a template file and extracts front-matter, returning the raw template bytes.
func (l *Loader) loadFragment(filename string) (map[string]any, []byte, error) {
if l.FS == nil {
return nil, nil, fmt.Errorf("error reading %s: no filesystem configured", filename)
}
template, err := fs.ReadFile(l.FS, filename)
if err != nil {
return nil, nil, fmt.Errorf("error reading %s: %w", filename, err)
}
// Extract front-matter
frontMatter, templateContent, err := extractFrontMatter(template)
if err != nil {
return nil, nil, err
}
return frontMatter, templateContent, nil
}