66 lines
1.7 KiB
Go
66 lines
1.7 KiB
Go
package skill
|
|
|
|
import (
|
|
"bufio"
|
|
"strings"
|
|
|
|
"gopkg.in/yaml.v3"
|
|
)
|
|
|
|
// Skill represents a loadable skill definition.
|
|
type Skill struct {
|
|
Name string `yaml:"name"`
|
|
Description string `yaml:"description"`
|
|
Active bool `yaml:"-"`
|
|
Content string `yaml:"-"` // markdown body after frontmatter
|
|
Path string `yaml:"-"` // file path
|
|
}
|
|
|
|
// parseFrontmatter extracts YAML frontmatter and markdown body from a skill file.
|
|
// Frontmatter is delimited by "---" on the first and closing lines.
|
|
func parseFrontmatter(data string) (*Skill, error) {
|
|
scanner := bufio.NewScanner(strings.NewReader(data))
|
|
|
|
// Check for opening "---".
|
|
if !scanner.Scan() || strings.TrimSpace(scanner.Text()) != "---" {
|
|
// No frontmatter — treat entire content as body.
|
|
return &Skill{Content: data}, nil
|
|
}
|
|
|
|
// Read YAML lines until closing "---".
|
|
var yamlBuf strings.Builder
|
|
foundEnd := false
|
|
for scanner.Scan() {
|
|
line := scanner.Text()
|
|
if strings.TrimSpace(line) == "---" {
|
|
foundEnd = true
|
|
break
|
|
}
|
|
yamlBuf.WriteString(line)
|
|
yamlBuf.WriteString("\n")
|
|
}
|
|
|
|
if !foundEnd {
|
|
// No closing delimiter — treat as body only.
|
|
return &Skill{Content: data}, nil
|
|
}
|
|
|
|
// Parse YAML frontmatter.
|
|
s := &Skill{}
|
|
if err := yaml.Unmarshal([]byte(yamlBuf.String()), s); err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
// Remaining content is the markdown body.
|
|
var bodyBuf strings.Builder
|
|
for scanner.Scan() {
|
|
if bodyBuf.Len() > 0 {
|
|
bodyBuf.WriteString("\n")
|
|
}
|
|
bodyBuf.WriteString(scanner.Text())
|
|
}
|
|
s.Content = strings.TrimSpace(bodyBuf.String())
|
|
|
|
return s, nil
|
|
}
|