mirror of
https://github.com/lukaszraczylo/harness-sync.git
synced 2026-10-12 00:45:22 +00:00
88 lines
2.2 KiB
Go
88 lines
2.2 KiB
Go
package common
|
|
|
|
import (
|
|
"os"
|
|
"path/filepath"
|
|
"strings"
|
|
|
|
"github.com/spf13/afero"
|
|
"gopkg.in/yaml.v3"
|
|
|
|
"github.com/lukaszraczylo/harness-sync/internal/fsx"
|
|
)
|
|
|
|
// Doc mirrors canonical.Skill / canonical.Agent without importing them.
|
|
type Doc struct {
|
|
Name string
|
|
Description string
|
|
Body string
|
|
Path string
|
|
}
|
|
|
|
// ParseFrontmatter extracts the name and description fields from a markdown
|
|
// file's YAML frontmatter block. Returns ("", "") when there is no frontmatter.
|
|
func ParseFrontmatter(b []byte) (name, description string) {
|
|
s := string(b)
|
|
if !strings.HasPrefix(s, "---\n") {
|
|
return "", ""
|
|
}
|
|
end := strings.Index(s[4:], "\n---")
|
|
if end == -1 {
|
|
return "", ""
|
|
}
|
|
var meta struct {
|
|
Name string `yaml:"name"`
|
|
Description string `yaml:"description"`
|
|
}
|
|
_ = yaml.Unmarshal([]byte(s[4:4+end]), &meta)
|
|
return meta.Name, meta.Description
|
|
}
|
|
|
|
// ImportMarkdownTreeFS walks dir on fs and returns one Doc per matching file.
|
|
// When requiredFilename is non-empty (e.g. "SKILL.md"), only files with that
|
|
// exact basename are included; otherwise any *.md.
|
|
func ImportMarkdownTreeFS(fs fsx.FS, dir, requiredFilename string) ([]Doc, error) {
|
|
var docs []Doc
|
|
if !DirExistsFS(fs, dir) {
|
|
return docs, nil
|
|
}
|
|
err := afero.Walk(fs, dir, func(p string, info os.FileInfo, err error) error {
|
|
if err != nil {
|
|
return err
|
|
}
|
|
if info.IsDir() {
|
|
return nil
|
|
}
|
|
if requiredFilename != "" && filepath.Base(p) != requiredFilename {
|
|
return nil
|
|
}
|
|
if requiredFilename == "" && !strings.HasSuffix(p, ".md") {
|
|
return nil
|
|
}
|
|
body, err := afero.ReadFile(fs, p)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
name, desc := ParseFrontmatter(body)
|
|
if name == "" {
|
|
name = strings.TrimSuffix(filepath.Base(p), ".md")
|
|
}
|
|
rel, _ := filepath.Rel(dir, p)
|
|
docs = append(docs, Doc{
|
|
Name: name,
|
|
Description: desc,
|
|
Body: string(body),
|
|
Path: rel,
|
|
})
|
|
return nil
|
|
})
|
|
return docs, err
|
|
}
|
|
|
|
// ImportMarkdownTree walks dir and returns one Doc per markdown file. When
|
|
// requiredFilename is non-empty (e.g. "SKILL.md"), only files with that exact
|
|
// basename are included; otherwise any *.md.
|
|
func ImportMarkdownTree(dir, requiredFilename string) ([]Doc, error) {
|
|
return ImportMarkdownTreeFS(fsx.OS(), dir, requiredFilename)
|
|
}
|