package content import ( "path/filepath" "strings" "github.com/insertr/insertr/internal/config" "github.com/insertr/insertr/internal/db" "github.com/insertr/insertr/internal/engine" ) // EnhancementConfig configures the enhancement pipeline type EnhancementConfig struct { Discovery config.DiscoveryConfig ContentInjection bool GenerateIDs bool } // Enhancer combines discovery, ID generation, and content injection in unified pipeline type Enhancer struct { engine *engine.ContentEngine config EnhancementConfig siteID string } // NewEnhancer creates a new HTML enhancer with unified pipeline func NewEnhancer(client db.ContentRepository, siteID string, config EnhancementConfig) *Enhancer { return &Enhancer{ engine: engine.NewContentEngine(client), config: config, siteID: siteID, } } // NewEnhancerWithAuth creates a new HTML enhancer with auth provider func NewEnhancerWithAuth(client db.ContentRepository, siteID string, config EnhancementConfig, authProvider *engine.AuthProvider) *Enhancer { return &Enhancer{ engine: engine.NewContentEngineWithAuth(client, authProvider), config: config, siteID: siteID, } } // NewDefaultEnhancer creates an enhancer with default configuration func NewDefaultEnhancer(client db.ContentRepository, siteID string) *Enhancer { defaultConfig := EnhancementConfig{ Discovery: config.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 engine func (e *Enhancer) EnhanceFile(inputPath, outputPath string) error { return e.engine.ProcessFile(inputPath, outputPath, e.siteID, engine.Enhancement) } // EnhanceDirectory processes all files in a directory through the engine func (e *Enhancer) EnhanceDirectory(inputDir, outputDir string) error { return e.engine.ProcessDirectory(inputDir, outputDir, e.siteID, engine.Enhancement) } // SetSiteID sets the site ID for the enhancer func (e *Enhancer) SetSiteID(siteID string) { e.siteID = siteID } // EnhanceInPlace performs in-place enhancement of static site files func (e *Enhancer) EnhanceInPlace(sitePath string, siteID string) error { // Use the provided siteID (derivation should happen at CLI level) e.siteID = siteID // Use EnhanceDirectory with same input and output (in-place) return e.EnhanceDirectory(sitePath, sitePath) } // DeriveOrValidateSiteID automatically derives site_id for demo paths or validates for production func DeriveOrValidateSiteID(sitePath string, configSiteID string) string { // Check if this is a demo path if strings.Contains(sitePath, "/demos/") || strings.Contains(sitePath, "./demos/") { return deriveDemoSiteID(sitePath) } // For non-demo paths, return the configured site_id // Validation of non-demo site_id will be handled at the CLI level return configSiteID } // deriveDemoSiteID extracts site_id from demo directory structure func deriveDemoSiteID(sitePath string) string { // Convert to absolute path and clean it absPath, err := filepath.Abs(sitePath) if err != nil { absPath = sitePath } absPath = filepath.Clean(absPath) // Flattened structure - just use directory name after demos/ // demos/default -> "default" // demos/simple -> "simple" // demos/dan-eden-portfolio -> "dan-eden-portfolio" parts := strings.Split(absPath, string(filepath.Separator)) // Find the demos directory index demosIndex := -1 for i, part := range parts { if part == "demos" { demosIndex = i break } } if demosIndex == -1 || demosIndex >= len(parts)-1 { // Fallback if demos not found in path return "default" } // Get the segment after demos/ and clean it dirName := parts[demosIndex+1] dirName = strings.TrimSuffix(dirName, "_enhanced") return dirName }