package generator import ( "bytes" "crypto/rand" "encoding/hex" "fmt" "html/template" "os" "path/filepath" ) // HTMLGenerator generates index.html only in dist folder type HTMLGenerator struct { projectDir string distDir string injector *ScriptInjector encryptionKey []byte } // NewHTMLGenerator creates a new HTML generator func NewHTMLGenerator(projectDir, distDir string) *HTMLGenerator { return &HTMLGenerator{ projectDir: projectDir, distDir: distDir, injector: NewScriptInjector(projectDir), } } // Generate creates the index.html in dist folder func (hg *HTMLGenerator) Generate(config *BuildConfig) error { // Load injected scripts if err := hg.injector.LoadScripts(); err != nil { return fmt.Errorf("failed to load injected scripts: %w", err) } // Generate encryption key at build time hg.encryptionKey = make([]byte, 32) if _, err := rand.Read(hg.encryptionKey); err != nil { return fmt.Errorf("failed to generate encryption key: %w", err) } // Create dist directory if err := os.MkdirAll(hg.distDir, 0755); err != nil { return fmt.Errorf("failed to create dist directory: %w", err) } // Generate HTML html, err := hg.buildHTML(config) if err != nil { return err } // Inject scripts html = hg.injector.InjectIntoHTML(html) // Write to dist indexPath := filepath.Join(hg.distDir, "index.html") if err := os.WriteFile(indexPath, []byte(html), 0644); err != nil { return fmt.Errorf("failed to write index.html: %w", err) } return nil } // BuildConfig holds build configuration type BuildConfig struct { Title string Description string BaseURL string APIBaseURL string DevMode bool Assets AssetManifest } // AssetManifest tracks generated assets type AssetManifest struct { JS []string CSS []string } func (hg *HTMLGenerator) buildHTML(config *BuildConfig) (string, error) { tmpl := ` {{.Title}} {{range .Assets.CSS}} {{end}}
{{range .Assets.JS}} {{end}} ` // Convert encryption key to array format for JS keyArray := make([]string, len(hg.encryptionKey)) for i, b := range hg.encryptionKey { keyArray[i] = fmt.Sprintf("%d", b) } keyArrayStr := "" for i, k := range keyArray { if i > 0 { keyArrayStr += "," } keyArrayStr += k } data := struct { Title string Description string BaseURL string APIBaseURL string DevMode bool Assets AssetManifest EncryptionKeyArray string }{ Title: config.Title, Description: config.Description, BaseURL: config.BaseURL, APIBaseURL: config.APIBaseURL, DevMode: config.DevMode, Assets: config.Assets, EncryptionKeyArray: keyArrayStr, } t, err := template.New("html").Parse(tmpl) if err != nil { return "", err } var buf bytes.Buffer if err := t.Execute(&buf, data); err != nil { return "", err } return buf.String(), nil } // GetEncryptionKeyHex returns the encryption key as hex for debugging func (hg *HTMLGenerator) GetEncryptionKeyHex() string { return hex.EncodeToString(hg.encryptionKey) }