Documentation
¶
Overview ¶
Package lifecycle provides the lifecycle management system for markata-go.
The lifecycle system orchestrates the build process through 9 stages:
- configure: Load configuration and initialize plugins
- validate: Validate configuration before processing
- glob: Discover content files
- load: Parse files into posts
- transform: Pre-render processing (jinja-md, etc.)
- render: Convert markdown to HTML
- collect: Build feeds, navigation, and aggregated content
- write: Write output files
- cleanup: Release resources
Plugin System ¶
Plugins implement optional interfaces corresponding to each stage:
type MyPlugin struct{}
func (p *MyPlugin) Name() string { return "my-plugin" }
func (p *MyPlugin) Load(m *Manager) error {
// Process files into posts
return nil
}
func (p *MyPlugin) Render(m *Manager) error {
// Render posts to HTML
return nil
}
Priority Ordering ¶
Plugins can implement PriorityPlugin to control execution order:
func (p *MyPlugin) Priority(stage Stage) int {
if stage == StageRender {
return PriorityLast // Run after other render plugins
}
return PriorityDefault
}
Usage ¶
Basic usage:
m := lifecycle.NewManager()
m.RegisterPlugin(&MyGlobPlugin{})
m.RegisterPlugin(&MyLoadPlugin{})
m.RegisterPlugin(&MyRenderPlugin{})
if err := m.Run(); err != nil {
log.Fatal(err)
}
Running up to a specific stage:
// Run only up to load stage (useful for preview/watch mode)
if err := m.RunTo(lifecycle.StageLoad); err != nil {
log.Fatal(err)
}
// Later, continue from where we left off
if err := m.Run(); err != nil {
log.Fatal(err)
}
Filtering and mapping posts:
// Get published posts
posts, _ := m.Filter("published==true")
// Get all titles of posts with tag "golang", sorted by date
titles, _ := m.Map("title", "tags contains golang", "date", true)
Index ¶
- Constants
- Variables
- func IsValidStage(s Stage) bool
- func StageIndex(s Stage) int
- type Cache
- type CleanupPlugin
- type CollectPlugin
- type Config
- type ConfigurePlugin
- type CriticalError
- type Feed
- type GlobPlugin
- type HookError
- type HookErrors
- type LoadPlugin
- type Manager
- func (m *Manager) AddFeed(feed *Feed)
- func (m *Manager) AddFile(file string)
- func (m *Manager) AddPost(post *models.Post)
- func (m *Manager) AssetHashes() map[string]string
- func (m *Manager) Cache() Cache
- func (m *Manager) Concurrency() int
- func (m *Manager) Config() *Config
- func (m *Manager) CurrentStage() Stage
- func (m *Manager) Feeds() []*Feed
- func (m *Manager) Files() []string
- func (m *Manager) Filter(expr string) ([]*models.Post, error)
- func (m *Manager) FilterPosts(predicate func(*models.Post) bool) []*models.Post
- func (m *Manager) GetAssetHash(path string) string
- func (m *Manager) HasRun(stage Stage) bool
- func (m *Manager) Map(field, filterExpr, sortField string, reverse bool) ([]interface{}, error)
- func (m *Manager) Plugins() []Plugin
- func (m *Manager) PostIndex() *PostIndex
- func (m *Manager) Posts() []*models.Post
- func (m *Manager) ProcessPostsConcurrently(fn func(*models.Post) error) error
- func (m *Manager) ProcessPostsSliceConcurrently(posts []*models.Post, fn func(*models.Post) error) error
- func (m *Manager) RegisterPlugin(p Plugin)
- func (m *Manager) RegisterPlugins(plugins ...Plugin)
- func (m *Manager) Reset()
- func (m *Manager) Run() error
- func (m *Manager) RunTo(stage Stage) error
- func (m *Manager) SetAssetHash(path, hash string)
- func (m *Manager) SetCache(cache Cache)
- func (m *Manager) SetConcurrency(n int)
- func (m *Manager) SetConfig(config *Config)
- func (m *Manager) SetFeeds(feeds []*Feed)
- func (m *Manager) SetFiles(files []string)
- func (m *Manager) SetPosts(posts []*models.Post)
- func (m *Manager) Warnings() []*HookError
- type Plugin
- type PostIndex
- type PriorityPlugin
- type RenderPlugin
- type Stage
- type TransformPlugin
- type ValidatePlugin
- type WritePlugin
Constants ¶
const ( // PriorityFirst ensures a plugin runs before most others. PriorityFirst = -1000 // PriorityEarly ensures a plugin runs early in the stage. PriorityEarly = -100 // PriorityDefault is the default priority. PriorityDefault = 0 // PriorityLate ensures a plugin runs late in the stage. PriorityLate = 100 // PriorityLast ensures a plugin runs after most others. PriorityLast = 1000 )
Priority constants for common ordering scenarios.
Variables ¶
var StageOrder = []Stage{ StageConfigure, StageValidate, StageGlob, StageLoad, StageTransform, StageRender, StageCollect, StageWrite, StageCleanup, }
StageOrder defines the execution order of all lifecycle stages.
Functions ¶
func IsValidStage ¶
IsValidStage checks if the given stage is a valid lifecycle stage.
func StageIndex ¶
StageIndex returns the index of a stage in the execution order. Returns -1 if the stage is not found.
Types ¶
type Cache ¶
type Cache interface {
Get(key string) (interface{}, bool)
Set(key string, value interface{})
Delete(key string)
Clear()
}
Cache is an interface for caching data between stages. Implementations must be thread-safe for concurrent access.
type CleanupPlugin ¶
CleanupPlugin is implemented by plugins that participate in the cleanup stage. This stage is used to release resources and perform cleanup tasks.
type CollectPlugin ¶
CollectPlugin is implemented by plugins that participate in the collect stage. This stage is used to build feeds, navigation, and other aggregated content.
type Config ¶
type Config struct {
// ContentDir is the directory containing content files.
ContentDir string
// OutputDir is the directory for generated output.
OutputDir string
// GlobPatterns are patterns to match content files.
GlobPatterns []string
// Extra holds additional configuration options.
Extra map[string]interface{}
}
Config holds markata configuration.
type ConfigurePlugin ¶
ConfigurePlugin is implemented by plugins that participate in the configure stage. This stage is used to load configuration and initialize plugin state.
type CriticalError ¶ added in v0.6.0
CriticalError is an interface that errors can implement to indicate they should be treated as critical errors that halt the build, regardless of which stage they occur in.
type Feed ¶
type Feed struct {
// Name is the feed identifier.
Name string
// Title is the feed title.
Title string
// Posts are the posts included in the feed.
Posts []*models.Post
// Content is the generated feed content.
Content string
// Path is the output path for the feed.
Path string
}
Feed represents a generated feed (RSS, Atom, etc.).
type GlobPlugin ¶
GlobPlugin is implemented by plugins that participate in the glob stage. This stage is used to discover content files.
type HookErrors ¶
type HookErrors struct {
Errors []*HookError
}
HookErrors is a collection of errors from hook execution.
func (*HookErrors) Add ¶
func (e *HookErrors) Add(stage Stage, plugin string, err error, critical bool)
Add adds an error to the collection.
func (*HookErrors) Error ¶
func (e *HookErrors) Error() string
func (*HookErrors) HasCritical ¶
func (e *HookErrors) HasCritical() bool
HasCritical returns true if any error is marked as critical.
type LoadPlugin ¶
LoadPlugin is implemented by plugins that participate in the load stage. This stage is used to parse files into posts.
type Manager ¶
type Manager struct {
// contains filtered or unexported fields
}
Manager orchestrates the lifecycle stages and plugin execution.
func NewManager ¶
func NewManager() *Manager
NewManager creates a new lifecycle Manager with default settings. Concurrency is auto-detected from CPU cores, capped at 16.
func (*Manager) AddPost ¶
AddPost adds a post to the posts slice. This invalidates the post index, which will be rebuilt on next access.
func (*Manager) AssetHashes ¶ added in v0.7.0
AssetHashes returns a copy of all registered asset hashes.
func (*Manager) Concurrency ¶
Concurrency returns the concurrency level.
func (*Manager) CurrentStage ¶
CurrentStage returns the currently executing stage.
func (*Manager) Filter ¶
Filter returns posts matching the given expression. The expression supports the AST-based filter syntax:
- "published == True" - field equals value
- "draft != True" - field not equals value
- "'go' in tags" - value in slice (or "tags contains go" for legacy syntax)
- "date <= today" - date comparisons with special values
- Multiple conditions can be combined with "and" or "or"
- Supports "not" for negation
func (*Manager) FilterPosts ¶ added in v0.6.0
FilterPosts returns a new slice containing only posts that match the predicate. This is useful for pre-filtering posts before processing:
changed := m.FilterPosts(func(p *models.Post) bool {
return cache.ShouldRebuild(p.Path, p.InputHash, p.Template)
})
return m.ProcessPostsSliceConcurrently(changed, processFunc)
func (*Manager) GetAssetHash ¶ added in v0.7.0
GetAssetHash retrieves the content hash for an asset path. Returns empty string if no hash is registered.
func (*Manager) Map ¶
Map extracts field values from posts, with optional filtering and sorting. Parameters:
- field: the field to extract (supports dot notation for nested fields)
- filterExpr: optional filter expression (same syntax as Filter)
- sortField: field to sort by (empty for no sorting)
- reverse: if true, sort in descending order
func (*Manager) PostIndex ¶ added in v0.6.0
PostIndex returns the shared post lookup index. The index is built lazily on first access and cached. It is automatically invalidated when posts are modified via SetPosts/AddPost.
func (*Manager) ProcessPostsConcurrently ¶
ProcessPostsConcurrently processes posts concurrently using a bounded worker pool. The worker pool is sized to Concurrency(), ensuring that regardless of post count, only a fixed number of goroutines are spawned. This eliminates scheduler overhead and memory churn for large builds.
Error handling: If any post fails to process, the function continues processing remaining posts and returns an aggregated error containing the count of failures and the first error encountered.
func (*Manager) ProcessPostsSliceConcurrently ¶ added in v0.6.0
func (m *Manager) ProcessPostsSliceConcurrently(posts []*models.Post, fn func(*models.Post) error) error
ProcessPostsSliceConcurrently processes the provided posts slice concurrently. This is useful when you have pre-filtered posts (e.g., only posts needing rebuild) and want to avoid iterating all posts.
Use this for incremental processing where you know only a subset of posts need work:
changedPosts := m.FilterPosts(func(p *models.Post) bool { return needsRebuild(p) })
return m.ProcessPostsSliceConcurrently(changedPosts, processFunc)
func (*Manager) RegisterPlugin ¶
RegisterPlugin adds a plugin to the manager. Plugins are executed in registration order within the same priority level.
func (*Manager) RegisterPlugins ¶
RegisterPlugins adds multiple plugins to the manager.
func (*Manager) Reset ¶
func (m *Manager) Reset()
Reset clears the manager state, allowing stages to be run again.
func (*Manager) RunTo ¶
RunTo executes lifecycle stages up to and including the specified stage. Already completed stages are skipped.
func (*Manager) SetAssetHash ¶ added in v0.7.0
SetAssetHash stores a content hash for an asset path (for cache busting). This is called by the static_assets plugin during the Write stage.
func (*Manager) SetConcurrency ¶
SetConcurrency sets the concurrency level for parallel processing.
type Plugin ¶
type Plugin interface {
// Name returns the unique name of the plugin.
Name() string
}
Plugin is the base interface that all plugins must implement.
type PostIndex ¶ added in v0.6.0
type PostIndex struct {
// BySlug maps lowercase slug to post
BySlug map[string]*models.Post
// BySlugified maps slugified versions (spaces->hyphens, lowercase) to post
BySlugified map[string]*models.Post
// ByHref maps href path to post
ByHref map[string]*models.Post
// ByPath maps file path to post
ByPath map[string]*models.Post
}
PostIndex provides efficient lookups for posts by various keys. This is built once after the Load stage and shared across all plugins to avoid each plugin building its own lookup maps.
func (*PostIndex) LookupBySlug ¶ added in v0.6.0
LookupBySlug finds a post by slug, trying exact match first then slugified. Returns nil if not found.
type PriorityPlugin ¶
type PriorityPlugin interface {
Plugin
// Priority returns the plugin's priority for a given stage.
// Lower values run first. Default priority is 0.
// Use negative values for "tryfirst" behavior.
// Use positive values for "trylast" behavior.
Priority(stage Stage) int
}
PriorityPlugin can be implemented by plugins to control execution order within a stage. Plugins with lower priority values run first.
type RenderPlugin ¶
RenderPlugin is implemented by plugins that participate in the render stage. This stage is used to convert markdown to HTML.
type Stage ¶
type Stage string
Stage represents a lifecycle stage in the markata build process.
const ( // StageConfigure loads config and initializes plugins. StageConfigure Stage = "configure" // StageValidate validates the configuration. StageValidate Stage = "validate" // StageGlob discovers content files. StageGlob Stage = "glob" // StageLoad parses files into posts. StageLoad Stage = "load" // StageTransform performs pre-render processing (jinja-md, etc.). StageTransform Stage = "transform" // StageRender converts markdown to HTML. StageRender Stage = "render" // StageCollect builds feeds and navigation. StageCollect Stage = "collect" // StageWrite writes output files. StageWrite Stage = "write" // StageCleanup releases resources. StageCleanup Stage = "cleanup" )
func StagesBefore ¶
StagesBefore returns all stages that come before the given stage.
func StagesUpTo ¶
StagesUpTo returns all stages up to and including the given stage.
type TransformPlugin ¶
TransformPlugin is implemented by plugins that participate in the transform stage. This stage is used for pre-render processing (jinja-md, etc.).
type ValidatePlugin ¶
ValidatePlugin is implemented by plugins that participate in the validate stage. This stage is used to validate configuration before processing begins.
type WritePlugin ¶
WritePlugin is implemented by plugins that participate in the write stage. This stage is used to write output files.