feature/recipe_implementation #5
@ -12,8 +12,8 @@ import (
|
||||
)
|
||||
|
||||
var (
|
||||
// stepRe still finds the headings (this one is solid)
|
||||
stepRe = regexp.MustCompile(`(?m)^### Step (\d+): (.+)$`)
|
||||
subRe = regexp.MustCompile(`(?m)^(\*\*(?:Objective|Instructions|Expected output):\*\*)\s*(.+?)(?:\n\n|\n###|\z)`)
|
||||
)
|
||||
|
||||
func Load(path string, userParams map[string]any) (*Recipe, error) {
|
||||
@ -45,7 +45,7 @@ func Load(path string, userParams map[string]any) (*Recipe, error) {
|
||||
}
|
||||
}
|
||||
|
||||
// Render templates
|
||||
// Render templates (so {{.package_path}} becomes "internal")
|
||||
tpl, err := template.New("recipe").Parse(string(parts[2]))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
@ -61,7 +61,7 @@ func Load(path string, userParams map[string]any) (*Recipe, error) {
|
||||
r.Overview = strings.TrimSpace(body[:idx])
|
||||
}
|
||||
|
||||
// Extract steps — split-based to guarantee no duplicates
|
||||
// Extract steps with robust multi-line parsing
|
||||
matches := stepRe.FindAllStringSubmatch(body, -1)
|
||||
for i, m := range matches {
|
||||
stepNum := i + 1
|
||||
@ -77,20 +77,42 @@ func Load(path string, userParams map[string]any) (*Recipe, error) {
|
||||
section := body[start:end]
|
||||
|
||||
step := Step{Number: stepNum, Title: title}
|
||||
for _, sub := range subRe.FindAllStringSubmatch(section, -1) {
|
||||
switch sub[1] {
|
||||
|
||||
// Simple, reliable label-based parsing (handles multi-line + blank lines)
|
||||
labels := []string{"**Objective:**", "**Instructions:**", "**Expected output:**"}
|
||||
for _, label := range labels {
|
||||
labelStart := strings.Index(section, label)
|
||||
if labelStart == -1 {
|
||||
continue
|
||||
}
|
||||
contentStart := labelStart + len(label)
|
||||
contentEnd := len(section)
|
||||
|
||||
// Find next label or end of section
|
||||
for _, nextLabel := range labels {
|
||||
next := strings.Index(section[contentStart:], nextLabel)
|
||||
if next != -1 {
|
||||
contentEnd = contentStart + next
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
content := strings.TrimSpace(section[contentStart:contentEnd])
|
||||
|
||||
switch label {
|
||||
case "**Objective:**":
|
||||
step.Objective = strings.TrimSpace(sub[2])
|
||||
step.Objective = content
|
||||
case "**Instructions:**":
|
||||
step.Instructions = strings.TrimSpace(sub[2])
|
||||
step.Instructions = content
|
||||
case "**Expected output:**":
|
||||
step.Expected = strings.TrimSpace(sub[2])
|
||||
step.Expected = content
|
||||
}
|
||||
}
|
||||
|
||||
r.Steps = append(r.Steps, step)
|
||||
}
|
||||
|
||||
// Final summary = everything after the last step
|
||||
// Final summary (everything after last step)
|
||||
if len(matches) > 0 {
|
||||
lastMatch := matches[len(matches)-1][0]
|
||||
lastIdx := strings.LastIndex(body, lastMatch)
|
||||
|
||||
Loading…
Reference in New Issue
Block a user