package content import ( "fmt" "golang.org/x/net/html" "os" "path/filepath" "strings" "github.com/insertr/insertr/internal/engine" ) // EnhancementConfig configures the enhancement pipeline type EnhancementConfig struct { Discovery DiscoveryConfig ContentInjection bool GenerateIDs bool } // DiscoveryConfig configures element discovery type DiscoveryConfig struct { Enabled bool Aggressive bool Containers bool Individual bool } // Enhancer combines discovery, ID generation, and content injection in unified pipeline type Enhancer struct { engine *engine.ContentEngine discoverer *Discoverer config EnhancementConfig siteID string } // NewEnhancer creates a new HTML enhancer with unified pipeline func NewEnhancer(client engine.ContentClient, siteID string, config EnhancementConfig) *Enhancer { return &Enhancer{ engine: engine.NewContentEngine(client), discoverer: NewDiscoverer(), config: config, siteID: siteID, } } // NewDefaultEnhancer creates an enhancer with default configuration func NewDefaultEnhancer(client engine.ContentClient, siteID string) *Enhancer { defaultConfig := EnhancementConfig{ Discovery: DiscoveryConfig{ Enabled: true, Aggressive: false, Containers: true, Individual: true, }, ContentInjection: true, GenerateIDs: true, } return NewEnhancer(client, siteID, defaultConfig) } // EnhanceFile processes a single HTML file through the complete pipeline func (e *Enhancer) EnhanceFile(inputPath, outputPath string) error { // Read HTML file htmlContent, err := os.ReadFile(inputPath) if err != nil { return fmt.Errorf("reading file %s: %w", inputPath, err) } // Process through unified pipeline processedHTML, err := e.processHTML(htmlContent, filepath.Base(inputPath)) if err != nil { return fmt.Errorf("processing HTML %s: %w", inputPath, err) } // Create output directory if err := os.MkdirAll(filepath.Dir(outputPath), 0755); err != nil { return fmt.Errorf("creating output directory: %w", err) } // Write processed HTML return os.WriteFile(outputPath, processedHTML, 0644) } // EnhanceDirectory processes all files in a directory through the unified pipeline func (e *Enhancer) EnhanceDirectory(inputDir, outputDir string) error { // Create output directory if err := os.MkdirAll(outputDir, 0755); err != nil { return fmt.Errorf("creating output directory: %w", err) } // Walk input directory return filepath.Walk(inputDir, func(path string, info os.FileInfo, err error) error { if err != nil { return err } // Calculate relative path and output path relPath, err := filepath.Rel(inputDir, path) if err != nil { return err } outputPath := filepath.Join(outputDir, relPath) // Handle directories if info.IsDir() { return os.MkdirAll(outputPath, info.Mode()) } // Process HTML files through enhancement pipeline if strings.HasSuffix(strings.ToLower(path), ".html") { return e.EnhanceFile(path, outputPath) } // Copy non-HTML files as-is return e.copyFile(path, outputPath) }) } // processHTML implements the unified enhancement pipeline func (e *Enhancer) processHTML(htmlContent []byte, filePath string) ([]byte, error) { var processedHTML []byte = htmlContent // Phase 1: Element Discovery (if enabled) if e.config.Discovery.Enabled { discoveredHTML, err := e.discoverElements(processedHTML, filePath) if err != nil { return nil, fmt.Errorf("element discovery: %w", err) } processedHTML = discoveredHTML } // Phase 2 & 3: ID Generation + Content Injection (via engine) if e.config.GenerateIDs || e.config.ContentInjection { enhancedHTML, err := e.enhanceWithEngine(processedHTML, filePath) if err != nil { return nil, fmt.Errorf("engine enhancement: %w", err) } processedHTML = enhancedHTML } return processedHTML, nil } // discoverElements adds insertr classes to viable elements func (e *Enhancer) discoverElements(htmlContent []byte, filePath string) ([]byte, error) { // Parse HTML doc, err := html.Parse(strings.NewReader(string(htmlContent))) if err != nil { return nil, fmt.Errorf("parsing HTML: %w", err) } // Find and mark viable elements result := &FileDiscoveryResult{Document: doc} e.discoverer.discoverNode(doc, result, e.config.Discovery.Aggressive) // Render back to HTML var buf strings.Builder if err := html.Render(&buf, doc); err != nil { return nil, fmt.Errorf("rendering HTML: %w", err) } return []byte(buf.String()), nil } // enhanceWithEngine uses the unified engine for ID generation and content injection func (e *Enhancer) enhanceWithEngine(htmlContent []byte, filePath string) ([]byte, error) { // Determine processing mode var mode engine.ProcessMode if e.config.ContentInjection { mode = engine.Enhancement // ID generation + content injection } else { mode = engine.IDGeneration // ID generation only } // Process with engine result, err := e.engine.ProcessContent(engine.ContentInput{ HTML: htmlContent, FilePath: filePath, SiteID: e.siteID, Mode: mode, }) if err != nil { return nil, fmt.Errorf("engine processing: %w", err) } // Render enhanced document var buf strings.Builder if err := html.Render(&buf, result.Document); err != nil { return nil, fmt.Errorf("rendering enhanced HTML: %w", err) } return []byte(buf.String()), nil } // EnhanceInPlace performs in-place enhancement of static site files func (e *Enhancer) EnhanceInPlace(sitePath string, siteID string) error { // TODO: Implement in-place enhancement using the unified pipeline fmt.Printf("📄 Enhancement requested for site %s at %s (unified pipeline implementation needed)\n", siteID, sitePath) return nil } // copyFile copies a file from src to dst func (e *Enhancer) copyFile(src, dst string) error { // Create directory for destination if err := os.MkdirAll(filepath.Dir(dst), 0755); err != nil { return err } // Read source data, err := os.ReadFile(src) if err != nil { return err } // Write destination return os.WriteFile(dst, data, 0644) }