diff --git a/manual/config.json b/manual/config.json new file mode 100644 index 00000000..2e1d606d --- /dev/null +++ b/manual/config.json @@ -0,0 +1,131 @@ +{ + "Sidebar": [ + { + "Title": "General", + "Items": [ + { + "Title": "Create Tag", + "Href": "/create_tag", + "IsDir": false + } + ] + }, + { + "Title": "Best Practices", + "Items": [ + { + "Title": "Osal", + "Href": "/best_practices/osal", + "IsDir": true, + "Children": [ + { + "Title": "Silence", + "Href": "/best_practices/osal/silence", + "IsDir": false + } + ] + }, + { + "Title": "Scripts", + "Href": "/best_practices/scripts", + "IsDir": true, + "Children": [ + { + "Title": "Scripts", + "Href": "/best_practices/scripts/scripts", + "IsDir": false + }, + { + "Title": "Shebang", + "Href": "/best_practices/scripts/shebang", + "IsDir": false + } + ] + }, + { + "Title": "Using Args In Function", + "Href": "/best_practices/using_args_in_function", + "IsDir": false + } + ] + }, + { + "Title": "Model Context Providers", + "Items": [ + { + "Title": "Baobab MCP", + "Href": "/Users/timurgordon/code/github/freeflowuniverse/herolib/lib/mcp/baobab/README.md", + "IsDir": false + } + ] + }, + { + "Title": "Core", + "Items": [ + { + "Title": "Base", + "Href": "/core/base", + "IsDir": false + }, + { + "Title": "Concepts", + "Href": "/core/concepts", + "IsDir": true, + "Children": [ + { + "Title": "Global Ids", + "Href": "/core/concepts/global_ids", + "IsDir": false + }, + { + "Title": "Name Registry", + "Href": "/core/concepts/name_registry", + "IsDir": false + }, + { + "Title": "Objects", + "Href": "/core/concepts/objects", + "IsDir": false + }, + { + "Title": "Sid", + "Href": "/core/concepts/sid", + "IsDir": false + } + ] + }, + { + "Title": "Context", + "Href": "/core/context", + "IsDir": false + }, + { + "Title": "Context Session Job", + "Href": "/core/context_session_job", + "IsDir": false + }, + { + "Title": "Play", + "Href": "/core/play", + "IsDir": false + }, + { + "Title": "Session", + "Href": "/core/session", + "IsDir": false + } + ] + }, + { + "Title": "Documentation", + "Items": [ + { + "Title": "Docextractor", + "Href": "/documentation/docextractor", + "IsDir": false + } + ] + } + ], + "Title": "HeroLib Manual" + } \ No newline at end of file diff --git a/manual/serve_wiki.sh b/manual/serve_wiki.sh index 0396147f..c4c70de3 100755 --- a/manual/serve_wiki.sh +++ b/manual/serve_wiki.sh @@ -8,290 +8,19 @@ echo "Starting HeroLib Manual Wiki Server..." # Get the directory of this script (manual directory) MANUAL_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" +# Get the directory of this script (manual directory) +CONFIG_FILE="$MANUAL_DIR/config.json" + # Path to the wiki package WIKI_DIR="/Users/timurgordon/code/github/freeflowuniverse/herolauncher/pkg/ui/wiki" # Path to the herolib directory HEROLIB_DIR="/Users/timurgordon/code/github/freeflowuniverse/herolib" -# Check if the wiki directory exists -if [ ! -d "$WIKI_DIR" ]; then - echo "Error: Wiki directory not found at $WIKI_DIR" - exit 1 -fi - -# Check if the herolib directory exists -if [ ! -d "$HEROLIB_DIR" ]; then - echo "Error: HeroLib directory not found at $HEROLIB_DIR" - exit 1 -fi - -# Create a local VFS instance for the manual directory -echo "Creating local VFS for manual directory: $MANUAL_DIR" -cd "$HEROLIB_DIR" - -# Create a temporary V program to initialize the VFS -TMP_DIR=$(mktemp -d) -VFS_INIT_FILE="$TMP_DIR/vfs_init.v" - -cat > "$VFS_INIT_FILE" << 'EOL' -module main - -import freeflowuniverse.herolib.vfs -import freeflowuniverse.herolib.vfs.vfs_local -import os - -fn main() { - if os.args.len < 2 { - println('Usage: vfs_init ') - exit(1) - } - - root_path := os.args[1] - println('Initializing local VFS with root path: ${root_path}') - - vfs_impl := vfs_local.new_local_vfs(root_path) or { - println('Error creating local VFS: ${err}') - exit(1) - } - - println('Local VFS initialized successfully') -} -EOL - -# Compile and run the VFS initialization program -cd "$TMP_DIR" -v "$VFS_INIT_FILE" -"$TMP_DIR/vfs_init" "$MANUAL_DIR" - -# Generate configuration JSON file with sidebar data -CONFIG_FILE="$TMP_DIR/wiki_config.json" -echo "Generating wiki configuration file: $CONFIG_FILE" - -# Create a temporary Go program to generate the sidebar configuration -SIDEBAR_GEN_FILE="$TMP_DIR/sidebar_gen.go" - -cat > "$SIDEBAR_GEN_FILE" << 'EOL' -package main - -import ( - "encoding/json" - "fmt" - "io/ioutil" - "os" - "path/filepath" - "strings" -) - -// SidebarItem represents an item in the sidebar -type SidebarItem struct { - Title string `json:"Title"` - Href string `json:"Href"` - IsDir bool `json:"IsDir"` - External bool `json:"External,omitempty"` - Children []SidebarItem `json:"Children,omitempty"` -} - -// SidebarSection represents a section in the sidebar -type SidebarSection struct { - Title string `json:"Title"` - Items []SidebarItem `json:"Items"` -} - -// Configuration represents the wiki configuration -type Configuration struct { - Sidebar []SidebarSection `json:"Sidebar"` - Title string `json:"Title,omitempty"` - BaseURL string `json:"BaseURL,omitempty"` -} - -func main() { - if len(os.Args) < 3 { - fmt.Println("Usage: sidebar_gen ") - os.Exit(1) - } - - contentPath := os.Args[1] - outputFile := os.Args[2] - - // Generate sidebar data - sidebar, err := generateSidebarFromPath(contentPath) - if err != nil { - fmt.Printf("Error generating sidebar: %v\n", err) - os.Exit(1) - } - - // Create configuration - config := Configuration{ - Sidebar: sidebar, - Title: "HeroLib Manual", - } - - // Write to file - configJSON, err := json.MarshalIndent(config, "", " ") - if err != nil { - fmt.Printf("Error marshaling JSON: %v\n", err) - os.Exit(1) - } - - err = ioutil.WriteFile(outputFile, configJSON, 0644) - if err != nil { - fmt.Printf("Error writing file: %v\n", err) - os.Exit(1) - } - - fmt.Printf("Configuration written to %s\n", outputFile) -} - -// Generate sidebar data from content path -func generateSidebarFromPath(contentPath string) ([]SidebarSection, error) { - // Get absolute path for content directory - absContentPath, err := filepath.Abs(contentPath) - if err != nil { - return nil, fmt.Errorf("error getting absolute path: %w", err) - } - - // Process top-level directories and files - dirs, err := ioutil.ReadDir(absContentPath) - if err != nil { - return nil, fmt.Errorf("error reading content directory: %w", err) - } - - // Create sections for each top-level directory - var sections []SidebarSection - - // Add files at the root level to a "General" section - var rootFiles []SidebarItem - - // Process directories and files - for _, dir := range dirs { - if dir.IsDir() { - // Process directory - dirPath := filepath.Join(absContentPath, dir.Name()) - // Pass the top-level directory name as the initial parent path - items, err := processDirectoryHierarchy(dirPath, absContentPath, dir.Name()) - if err != nil { - return nil, fmt.Errorf("error processing directory %s: %w", dir.Name(), err) - } - - if len(items) > 0 { - sections = append(sections, SidebarSection{ - Title: formatTitle(dir.Name()), - Items: items, - }) - } - } else if isMarkdownFile(dir.Name()) { - // Add root level markdown files to the General section - filePath := filepath.Join(absContentPath, dir.Name()) - fileItem := createSidebarItemFromFile(filePath, absContentPath, "") - rootFiles = append(rootFiles, fileItem) - } - } - - // Add root files to a General section if there are any - if len(rootFiles) > 0 { - sections = append([]SidebarSection{{ - Title: "General", - Items: rootFiles, - }}, sections...) - } - - return sections, nil -} - -// Process a directory and return a hierarchical structure of sidebar items -func processDirectoryHierarchy(dirPath, rootPath, parentPath string) ([]SidebarItem, error) { - entries, err := ioutil.ReadDir(dirPath) - if err != nil { - return nil, fmt.Errorf("error reading directory %s: %w", dirPath, err) - } - - var items []SidebarItem - - // Process all entries in the directory - for _, entry := range entries { - entryPath := filepath.Join(dirPath, entry.Name()) - relPath := filepath.Join(parentPath, entry.Name()) - - if entry.IsDir() { - // Process subdirectory - subItems, err := processDirectoryHierarchy(entryPath, rootPath, relPath) - if err != nil { - return nil, err - } - - if len(subItems) > 0 { - // Create a directory item with children - items = append(items, SidebarItem{ - Title: formatTitle(entry.Name()), - Href: "/" + relPath, // Add leading slash - IsDir: true, - Children: subItems, - }) - } - } else if isMarkdownFile(entry.Name()) { - // Process markdown file - fileItem := createSidebarItemFromFile(entryPath, rootPath, parentPath) - items = append(items, fileItem) - } - } - - return items, nil -} - -// Create a sidebar item from a file path -func createSidebarItemFromFile(filePath, rootPath, parentPath string) SidebarItem { - fileName := filepath.Base(filePath) - baseName := strings.TrimSuffix(fileName, filepath.Ext(fileName)) - relPath := filepath.Join(parentPath, baseName) - - return SidebarItem{ - Title: formatTitle(baseName), - Href: "/" + relPath, // Add leading slash for proper URL formatting - IsDir: false, - } -} - -// Format a title from a file or directory name -func formatTitle(name string) string { - // Replace underscores and hyphens with spaces - name = strings.ReplaceAll(name, "_", " ") - name = strings.ReplaceAll(name, "-", " ") - - // Capitalize the first letter of each word - words := strings.Fields(name) - for i, word := range words { - if len(word) > 0 { - words[i] = strings.ToUpper(word[0:1]) + word[1:] - } - } - - return strings.Join(words, " ") -} - -// Check if a file is a markdown file -func isMarkdownFile(fileName string) bool { - ext := strings.ToLower(filepath.Ext(fileName)) - return ext == ".md" || ext == ".markdown" -} -EOL - -# Compile and run the sidebar generator -cd "$TMP_DIR" -go build -o sidebar_gen "$SIDEBAR_GEN_FILE" -"$TMP_DIR/sidebar_gen" "$MANUAL_DIR" "$CONFIG_FILE" - -# Start the wiki server with the manual directory as the content path and config file -echo "Serving manual content from: $MANUAL_DIR" -echo "Using wiki server from: $WIKI_DIR" cd "$WIKI_DIR" -# Display the generated configuration for debugging -echo "Generated configuration:" -cat "$CONFIG_FILE" | head -n 30 - # Run the wiki server on port 3004 -go run main.go "$MANUAL_DIR" "$CONFIG_FILE" 3004 +go run . "$MANUAL_DIR" "$CONFIG_FILE" 3004 # The script will not reach this point unless the server is stopped echo "Wiki server stopped."