Files
freezelib/config.go
2025-07-18 19:02:23 +08:00

243 lines
5.9 KiB
Go

package freezelib
import (
"fmt"
"strconv"
"strings"
)
// Config represents the configuration for generating code screenshots
type Config struct {
// Window settings
Background string `json:"background"`
Margin []float64 `json:"margin"`
Padding []float64 `json:"padding"`
Window bool `json:"window"`
Width float64 `json:"width"`
Height float64 `json:"height"`
// Language and theme
Language string `json:"language"`
Theme string `json:"theme"`
Wrap int `json:"wrap"`
// Decoration
Border Border `json:"border"`
Shadow Shadow `json:"shadow"`
// Font
Font Font `json:"font"`
// Line settings
LineHeight float64 `json:"line_height"`
Lines []int `json:"lines"`
ShowLineNumbers bool `json:"show_line_numbers"`
}
// Shadow configuration for drop shadow effects
type Shadow struct {
Blur float64 `json:"blur"`
X float64 `json:"x"`
Y float64 `json:"y"`
}
// Border configuration for window borders
type Border struct {
Radius float64 `json:"radius"`
Width float64 `json:"width"`
Color string `json:"color"`
}
// Font configuration
type Font struct {
Family string `json:"family"`
File string `json:"file"`
Size float64 `json:"size"`
Ligatures bool `json:"ligatures"`
}
// DefaultConfig returns a default configuration
func DefaultConfig() *Config {
return &Config{
Background: "#171717",
Margin: []float64{0},
Padding: []float64{20},
Window: false,
Width: 0,
Height: 0,
Language: "",
Theme: "charm",
Wrap: 0,
Border: Border{Radius: 0, Width: 0, Color: "#515151"},
Shadow: Shadow{Blur: 0, X: 0, Y: 0},
Font: Font{Family: "JetBrains Mono", Size: 14, Ligatures: true},
LineHeight: 1.2,
Lines: []int{},
ShowLineNumbers: false,
}
}
// SetPadding sets padding for all sides or specific sides
// Accepts 1, 2, or 4 values like CSS padding
func (c *Config) SetPadding(values ...float64) *Config {
c.Padding = values
return c
}
// SetMargin sets margin for all sides or specific sides
// Accepts 1, 2, or 4 values like CSS margin
func (c *Config) SetMargin(values ...float64) *Config {
c.Margin = values
return c
}
// SetFont sets font family and size
func (c *Config) SetFont(family string, size float64) *Config {
c.Font.Family = family
c.Font.Size = size
return c
}
// SetTheme sets the syntax highlighting theme
func (c *Config) SetTheme(theme string) *Config {
c.Theme = theme
return c
}
// SetLanguage sets the programming language for syntax highlighting
func (c *Config) SetLanguage(language string) *Config {
c.Language = language
return c
}
// SetBackground sets the background color
func (c *Config) SetBackground(color string) *Config {
c.Background = color
return c
}
// SetWindow enables or disables window controls
func (c *Config) SetWindow(enabled bool) *Config {
c.Window = enabled
return c
}
// SetLineNumbers enables or disables line numbers
func (c *Config) SetLineNumbers(enabled bool) *Config {
c.ShowLineNumbers = enabled
return c
}
// SetShadow sets shadow properties
func (c *Config) SetShadow(blur, x, y float64) *Config {
c.Shadow = Shadow{Blur: blur, X: x, Y: y}
return c
}
// SetBorder sets border properties
func (c *Config) SetBorder(width, radius float64, color string) *Config {
c.Border = Border{Width: width, Radius: radius, Color: color}
return c
}
// SetDimensions sets the output dimensions
func (c *Config) SetDimensions(width, height float64) *Config {
c.Width = width
c.Height = height
return c
}
// SetLines sets the line range to capture (1-indexed)
func (c *Config) SetLines(start, end int) *Config {
if start > 0 && end > 0 && start <= end {
c.Lines = []int{start - 1, end - 1} // Convert to 0-indexed
}
return c
}
// expandPadding expands padding values according to CSS rules
func (c *Config) expandPadding(scale float64) []float64 {
p := c.Padding
switch len(p) {
case 1:
return []float64{p[0] * scale, p[0] * scale, p[0] * scale, p[0] * scale}
case 2:
return []float64{p[0] * scale, p[1] * scale, p[0] * scale, p[1] * scale}
case 4:
return []float64{p[0] * scale, p[1] * scale, p[2] * scale, p[3] * scale}
default:
return []float64{0, 0, 0, 0}
}
}
// expandMargin expands margin values according to CSS rules
func (c *Config) expandMargin(scale float64) []float64 {
m := c.Margin
switch len(m) {
case 1:
return []float64{m[0] * scale, m[0] * scale, m[0] * scale, m[0] * scale}
case 2:
return []float64{m[0] * scale, m[1] * scale, m[0] * scale, m[1] * scale}
case 4:
return []float64{m[0] * scale, m[1] * scale, m[2] * scale, m[3] * scale}
default:
return []float64{0, 0, 0, 0}
}
}
// Clone creates a deep copy of the configuration
func (c *Config) Clone() *Config {
clone := *c
clone.Margin = make([]float64, len(c.Margin))
copy(clone.Margin, c.Margin)
clone.Padding = make([]float64, len(c.Padding))
copy(clone.Padding, c.Padding)
clone.Lines = make([]int, len(c.Lines))
copy(clone.Lines, c.Lines)
return &clone
}
// Validate checks if the configuration is valid
func (c *Config) Validate() error {
if c.Font.Size <= 0 {
return fmt.Errorf("font size must be positive")
}
if c.LineHeight <= 0 {
return fmt.Errorf("line height must be positive")
}
if len(c.Lines) == 2 && c.Lines[0] > c.Lines[1] {
return fmt.Errorf("start line must be less than or equal to end line")
}
return nil
}
// parseColor validates and normalizes color values
func parseColor(color string) string {
color = strings.TrimSpace(color)
if color == "" {
return "#000000"
}
if !strings.HasPrefix(color, "#") {
color = "#" + color
}
return color
}
// dimensionToInt converts dimension strings to integers
func dimensionToInt(dimension string) int {
dimension = strings.TrimSuffix(dimension, "px")
val, err := strconv.Atoi(dimension)
if err != nil {
return 0
}
return val
}
// side constants for padding/margin indexing
const (
top = 0
right = 1
bottom = 2
left = 3
)