Refactor architecture: eliminate auto-discovery and consolidate packages
- Remove auto-discovery entirely (~450 lines) * Delete internal/content/discoverer.go * Simplify enhancer to single-phase processing * Remove duplicate container expansion logic - Consolidate repository implementations * Move internal/content/client.go → internal/db/http_client.go * Group all repository implementations in db/ package - Add file utilities to engine following Go stdlib patterns * Add engine.ProcessFile() and ProcessDirectory() methods * Engine now handles both content processing AND file operations - Move site management to dedicated package * Move internal/content/site_manager.go → internal/sites/manager.go * Clear separation of site lifecycle from content processing - Preserve container expansion (syntactic sugar) * .insertr on containers still auto-applies to viable children * Container detection logic consolidated in engine/utils.go Result: Clean architecture with single source of truth for .insertr processing
This commit is contained in:
@@ -1,9 +1,6 @@
|
||||
package content
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"golang.org/x/net/html"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
|
||||
@@ -14,46 +11,40 @@ import (
|
||||
|
||||
// EnhancementConfig configures the enhancement pipeline
|
||||
type EnhancementConfig struct {
|
||||
Discovery DiscoveryConfig
|
||||
Discovery config.DiscoveryConfig
|
||||
ContentInjection bool
|
||||
GenerateIDs bool
|
||||
}
|
||||
|
||||
// Type alias for backward compatibility
|
||||
type DiscoveryConfig = config.DiscoveryConfig
|
||||
|
||||
// Enhancer combines discovery, ID generation, and content injection in unified pipeline
|
||||
type Enhancer struct {
|
||||
engine *engine.ContentEngine
|
||||
discoverer *Discoverer
|
||||
config EnhancementConfig
|
||||
siteID string
|
||||
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),
|
||||
discoverer: NewDiscoverer(),
|
||||
config: config,
|
||||
siteID: siteID,
|
||||
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),
|
||||
discoverer: NewDiscoverer(),
|
||||
config: config,
|
||||
siteID: siteID,
|
||||
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: DiscoveryConfig{
|
||||
Discovery: config.DiscoveryConfig{
|
||||
Enabled: true,
|
||||
Aggressive: false,
|
||||
Containers: true,
|
||||
@@ -65,138 +56,14 @@ func NewDefaultEnhancer(client db.ContentRepository, siteID string) *Enhancer {
|
||||
return NewEnhancer(client, siteID, defaultConfig)
|
||||
}
|
||||
|
||||
// EnhanceFile processes a single HTML file through the complete pipeline
|
||||
// EnhanceFile processes a single HTML file through the engine
|
||||
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)
|
||||
return e.engine.ProcessFile(inputPath, outputPath, e.siteID, engine.Enhancement)
|
||||
}
|
||||
|
||||
// EnhanceDirectory processes all files in a directory through the unified pipeline
|
||||
// EnhanceDirectory processes all files in a directory through the engine
|
||||
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
|
||||
return e.engine.ProcessDirectory(inputDir, outputDir, e.siteID, engine.Enhancement)
|
||||
}
|
||||
|
||||
// SetSiteID sets the site ID for the enhancer
|
||||
@@ -261,20 +128,3 @@ func deriveDemoSiteID(sitePath string) string {
|
||||
|
||||
return dirName
|
||||
}
|
||||
|
||||
// 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)
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user