Thanks to visit codestin.com
Credit goes to github.com

Skip to content

cpcf/weft

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

37 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

noun - the horizontal threads in weaving, creating the fabric's structure.

weft

A Go template engine for code generation with extensible post-processing, state management, debugging, and testing utilities.

Packages

  • config - Generic YAML configuration loading with validation support
  • engine - Core template processing with caching and concurrent rendering
  • postprocess - Extensible post-processing framework for transforming generated content
  • processors - Built-in post-processors (Go imports, whitespace cleanup, headers, etc.)
  • render - Template discovery, blocks, includes, and function registry
  • write - File writing with coordination, locking, and composite operations
  • state - File tracking, manifest management, and cleanup operations
  • debug - Debugging, error handling, and template validation
  • testing - Testing utilities, benchmarks, mocks, and snapshots

Basic Usage

package main

import (
    "github.com/cpcf/weft/engine"
    "github.com/cpcf/weft/processors"
)

func main() {
    // Create template engine
    eng := engine.New(
        engine.WithOutputRoot("./generated"),
        engine.WithFailureMode(engine.FailFast),
    )

    // Add post-processors for generated content
    eng.AddPostProcessor(processors.NewGoImports())                // Fix Go imports & formatting
    eng.AddPostProcessor(processors.NewTrimWhitespace())           // Clean whitespace
    eng.AddPostProcessor(processors.NewAddGeneratedHeader("myapp", ".go")) // Add headers
    
    // Create context
    ctx := engine.NewContext(templateFS, "./generated", "mypackage")
    
    // Render templates with post-processing
    if err := eng.RenderDir(ctx, "templates", data); err != nil {
        log.Fatal(err)
    }
}

Custom Template Functions

weft supports custom template functions alongside its built-in functions:

import (
    "text/template"
    "time"
    "github.com/cpcf/weft/engine"
)

// Define custom functions
customFuncs := template.FuncMap{
    "formatDate": func(t time.Time) string {
        return t.Format("2006-01-02")
    },
    "calculateTax": func(amount float64, rate float64) float64 {
        return amount * rate
    },
}

// Create engine with custom functions
eng := engine.New(
    engine.WithCustomFunctions(customFuncs),
    engine.WithOutputRoot("./generated"),
)

// Use in templates:
// {{formatDate .CreatedAt}}
// {{calculateTax .Amount 0.08}}

Post-Processing System

weft includes an extensible post-processing framework that transforms generated content:

Built-in Processors

  • Go Imports - Automatically fixes imports and formats Go code using goimports
  • Trim Whitespace - Removes trailing whitespace from all lines
  • Generated Headers - Adds "Code generated" headers to files
  • Regex Replace - Custom regex-based transformations

Custom Processors

Create custom processors by implementing the postprocess.Processor interface:

type MyProcessor struct{}

func (p *MyProcessor) ProcessContent(filePath string, content []byte) ([]byte, error) {
    if strings.HasSuffix(filePath, ".go") {
        // Custom Go transformations
        return transformGoCode(content), nil
    }
    return content, nil
}

// Add to engine
eng.AddPostProcessor(&MyProcessor{})

Function-based Processors

For simple transformations, use function processors:

eng.AddPostProcessorFunc(func(filePath string, content []byte) ([]byte, error) {
    // Convert line endings to Unix style
    return bytes.ReplaceAll(content, []byte("\r\n"), []byte("\n")), nil
})

See postprocess/README.md for comprehensive documentation.

Configuration Loading

The config package provides utilities for loading YAML configuration files into your custom types:

import "github.com/cpcf/weft/config"

type MyConfig struct {
    Name    string            `yaml:"name"`
    Version string            `yaml:"version"`
    Options map[string]string `yaml:"options"`
}

func main() {
    var cfg MyConfig
    
    // Load configuration from YAML file
    err := config.LoadYAML("config.yaml", &cfg)
    if err != nil {
        log.Fatal(err)
    }
    
    // Use configuration with template engine
    eng := engine.New(engine.WithOutputRoot(cfg.Options["output_dir"]))
    // ...
}

See config/README.md for detailed documentation including validation and testing utilities.

Examples