...
This commit is contained in:
171
pkg/data/doctree/include.go
Normal file
171
pkg/data/doctree/include.go
Normal file
@@ -0,0 +1,171 @@
|
||||
package doctree
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"strings"
|
||||
|
||||
"github.com/freeflowuniverse/heroagent/pkg/tools"
|
||||
)
|
||||
|
||||
// Global variable to track the current DocTree instance
|
||||
var currentDocTree *DocTree
|
||||
|
||||
// processIncludeLine processes a single line for include directives
|
||||
// Returns collectionName and pageName if found, or empty strings if not an include directive
|
||||
//
|
||||
// Supports:
|
||||
// !!include collectionname:'pagename'
|
||||
// !!include collectionname:'pagename.md'
|
||||
// !!include 'pagename'
|
||||
// !!include collectionname:pagename
|
||||
// !!include collectionname:pagename.md
|
||||
// !!include name:'pagename'
|
||||
// !!include pagename
|
||||
func parseIncludeLine(line string) (string, string, error) {
|
||||
// Check if the line contains an include directive
|
||||
if !strings.Contains(line, "!!include") {
|
||||
return "", "", nil
|
||||
}
|
||||
|
||||
// Extract the part after !!include
|
||||
parts := strings.SplitN(line, "!!include", 2)
|
||||
if len(parts) != 2 {
|
||||
return "", "", fmt.Errorf("malformed include directive: %s", line)
|
||||
}
|
||||
|
||||
// Trim spaces and check if the include part is empty
|
||||
includeText := tools.TrimSpacesAndQuotes(parts[1])
|
||||
if includeText == "" {
|
||||
return "", "", fmt.Errorf("empty include directive: %s", line)
|
||||
}
|
||||
|
||||
// Remove name: prefix if present
|
||||
if strings.HasPrefix(includeText, "name:") {
|
||||
includeText = strings.TrimSpace(strings.TrimPrefix(includeText, "name:"))
|
||||
if includeText == "" {
|
||||
return "", "", fmt.Errorf("empty page name after 'name:' prefix: %s", line)
|
||||
}
|
||||
}
|
||||
|
||||
// Check if it contains a collection reference (has a colon)
|
||||
if strings.Contains(includeText, ":") {
|
||||
parts := strings.SplitN(includeText, ":", 2)
|
||||
if len(parts) != 2 {
|
||||
return "", "", fmt.Errorf("malformed collection reference: %s", includeText)
|
||||
}
|
||||
|
||||
collectionName := tools.NameFix(parts[0])
|
||||
pageName := tools.NameFix(parts[1])
|
||||
|
||||
if collectionName == "" {
|
||||
return "", "", fmt.Errorf("empty collection name in include directive: %s", line)
|
||||
}
|
||||
|
||||
if pageName == "" {
|
||||
return "", "", fmt.Errorf("empty page name in include directive: %s", line)
|
||||
}
|
||||
|
||||
return collectionName, pageName, nil
|
||||
}
|
||||
|
||||
return "", includeText, nil
|
||||
}
|
||||
|
||||
// processIncludes handles all the different include directive formats in markdown
|
||||
func processIncludes(content string, currentCollectionName string, dt *DocTree) string {
|
||||
|
||||
// Find all include directives
|
||||
lines := strings.Split(content, "\n")
|
||||
result := make([]string, 0, len(lines))
|
||||
|
||||
for _, line := range lines {
|
||||
collectionName, pageName, err := parseIncludeLine(line)
|
||||
if err != nil {
|
||||
errorMsg := fmt.Sprintf(">>ERROR: Failed to process include directive: %v", err)
|
||||
result = append(result, errorMsg)
|
||||
continue
|
||||
}
|
||||
|
||||
if collectionName == "" && pageName == "" {
|
||||
// Not an include directive, keep the line
|
||||
result = append(result, line)
|
||||
} else {
|
||||
includeContent := ""
|
||||
var includeErr error
|
||||
|
||||
// If no collection specified, use the current collection
|
||||
if collectionName == "" {
|
||||
collectionName = currentCollectionName
|
||||
}
|
||||
|
||||
// Process the include
|
||||
includeContent, includeErr = handleInclude(pageName, collectionName, dt)
|
||||
|
||||
if includeErr != nil {
|
||||
errorMsg := fmt.Sprintf(">>ERROR: %v", includeErr)
|
||||
result = append(result, errorMsg)
|
||||
} else {
|
||||
// Process any nested includes in the included content
|
||||
processedIncludeContent := processIncludes(includeContent, collectionName, dt)
|
||||
result = append(result, processedIncludeContent)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return strings.Join(result, "\n")
|
||||
}
|
||||
|
||||
// handleInclude processes the include directive with the given page name and optional collection name
|
||||
func handleInclude(pageName, collectionName string, dt *DocTree) (string, error) {
|
||||
// Check if it's from another collection
|
||||
if collectionName != "" {
|
||||
// Format: othercollection:pagename
|
||||
namefixedCollectionName := tools.NameFix(collectionName)
|
||||
|
||||
// Remove .md extension if present for the API call
|
||||
namefixedPageName := tools.NameFix(pageName)
|
||||
namefixedPageName = strings.TrimSuffix(namefixedPageName, ".md")
|
||||
|
||||
// Try to get the collection from the DocTree
|
||||
// First check if the collection exists in the current DocTree
|
||||
otherCollection, err := dt.GetCollection(namefixedCollectionName)
|
||||
if err != nil {
|
||||
// If not found in the current DocTree, check the global currentDocTree
|
||||
if currentDocTree != nil && currentDocTree != dt {
|
||||
otherCollection, err = currentDocTree.GetCollection(namefixedCollectionName)
|
||||
if err != nil {
|
||||
return "", fmt.Errorf("cannot include from non-existent collection: %s", collectionName)
|
||||
}
|
||||
} else {
|
||||
return "", fmt.Errorf("cannot include from non-existent collection: %s", collectionName)
|
||||
}
|
||||
}
|
||||
|
||||
// Get the page content using the collection's PageGet method
|
||||
content, err := otherCollection.PageGet(namefixedPageName)
|
||||
if err != nil {
|
||||
return "", fmt.Errorf("cannot include non-existent page: %s from collection: %s", pageName, collectionName)
|
||||
}
|
||||
|
||||
return content, nil
|
||||
} else {
|
||||
// For same collection includes, we need to get the current collection
|
||||
currentCollection, err := dt.GetCollection(dt.defaultCollection)
|
||||
if err != nil {
|
||||
return "", fmt.Errorf("failed to get current collection: %w", err)
|
||||
}
|
||||
|
||||
// Include from the same collection
|
||||
// Remove .md extension if present for the API call
|
||||
namefixedPageName := tools.NameFix(pageName)
|
||||
namefixedPageName = strings.TrimSuffix(namefixedPageName, ".md")
|
||||
|
||||
// Use the current collection to get the page content
|
||||
content, err := currentCollection.PageGet(namefixedPageName)
|
||||
if err != nil {
|
||||
return "", fmt.Errorf("cannot include non-existent page: %s", pageName)
|
||||
}
|
||||
|
||||
return content, nil
|
||||
}
|
||||
}
|
Reference in New Issue
Block a user