AshReports.FormatSpecification (ash_reports v0.1.0)
Format Specification DSL for AshReports.
This module provides a comprehensive DSL for defining custom formatting patterns that extend beyond the standard CLDR formatting capabilities. Format specifications allow for sophisticated control over how data is presented in reports across all output formats (HTML, HEEX, PDF, JSON).
Features
- Custom Format Patterns: Define complex formatting rules using intuitive syntax
- Type-Specific Formatting: Specialized formatting for numbers, currencies, dates, and text
- Conditional Formatting: Apply different formats based on data values or conditions
- Locale Integration: Works seamlessly with existing CLDR locale support
- Cross-Renderer Support: Format specifications work across all output renderers
- Performance Optimized: Compiled format specifications for efficient processing
Format Specification Syntax
Format specifications use a declarative syntax that combines pattern strings with configuration options:
Basic Pattern Syntax
# Number formatting with custom precision and separators
format_spec :custom_number do
pattern "#,##0.000"
locale_aware true
end
# Currency formatting with symbol placement
format_spec :custom_currency do
pattern "¤ #,##0.00"
currency :USD
symbol_position :prefix
end
# Date formatting with custom patterns
format_spec :custom_date do
pattern "dd/MM/yyyy"
locale "en-GB"
endConditional Formatting
# Apply different formats based on value ranges
format_spec :conditional_number do
condition value > 1000, pattern: "#,##0K", color: :green
condition value < 0, pattern: "(#,##0)", color: :red
default pattern: "#,##0.00"
endAdvanced Pattern Features
# Text formatting with transformations
format_spec :custom_text do
pattern "%{value}"
transform :uppercase
max_length 50
truncate_suffix "..."
end
# Percentage formatting with custom display
format_spec :custom_percentage do
pattern "#0.##%"
multiplier 100
suffix " percent"
endIntegration with Renderers
Format specifications integrate seamlessly with all AshReports renderers:
In Element Definitions
field :amount do
source :total_amount
format_spec :custom_currency
end
expression :growth_rate do
expression expr(current / previous - 1)
format_spec :custom_percentage
endIn Band Processing
band :summary do
elements do
field :total do
source :sum_amount
format_spec conditional_number: [
{value > 10000, pattern: "$#,##0K", color: :green},
{value < 0, pattern: "($#,##0)", color: :red}
]
end
end
endPerformance Considerations
- Format Compilation: Specifications are compiled at DSL build time for performance
- Caching: Compiled formatters are cached per locale and specification
- Lazy Evaluation: Complex conditional formats are evaluated only when needed
- Memory Efficiency: Format specifications share common components
Error Handling
Format specifications include comprehensive error handling:
- Pattern Validation: Syntax validation at compile time
- Runtime Fallbacks: Graceful degradation when formatting fails
- Type Checking: Ensures format compatibility with data types
- Locale Validation: Verifies locale availability for format operations
Summary
Types
Conditional formatting rule
Format pattern string with placeholders and formatting directives
Format specification result
Format specification configuration
Format specification identifier
Functions
Adds a conditional formatting rule to a format specification.
Compiles a format specification for efficient runtime use.
Gets the effective format pattern for a given value and context.
Creates a new format specification with the given name and configuration.
Sets the default formatting pattern for a specification.
Validates a format specification without compiling it.
Types
Conditional formatting rule
@type format_pattern() :: String.t()
Format pattern string with placeholders and formatting directives
Format specification result
@type format_spec() :: %{ name: format_spec_name(), pattern: format_pattern() | nil, conditions: [condition_rule()], options: keyword(), compiled: boolean() }
Format specification configuration
@type format_spec_name() :: atom()
Format specification identifier
Functions
@spec add_condition(format_spec(), any(), keyword()) :: format_spec()
Adds a conditional formatting rule to a format specification.
Conditional rules are evaluated in order, with the first matching condition being applied. If no conditions match, the default pattern is used.
Parameters
spec- The format specification to modifycondition- The condition expression to evaluateformat_options- Formatting options to apply when condition is true
Examples
spec = AshReports.FormatSpecification.new(:conditional_amount)
|> AshReports.FormatSpecification.add_condition(
expr(value > 1000),
pattern: "#,##0K",
color: :green
)
|> AshReports.FormatSpecification.add_condition(
expr(value < 0),
pattern: "(#,##0)",
color: :red
)
@spec compile(format_spec()) :: {:ok, format_spec()} | {:error, term()}
Compiles a format specification for efficient runtime use.
Compilation validates the format patterns, optimizes condition evaluation, and prepares the specification for integration with the formatting system.
Parameters
spec- The format specification to compile
Returns
Returns {:ok, compiled_spec} on success or {:error, reason} if compilation fails.
Examples
spec = AshReports.FormatSpecification.new(:my_format, pattern: "#,##0.00")
{:ok, compiled} = AshReports.FormatSpecification.compile(spec)
@spec get_effective_format(format_spec(), any(), map()) :: {:ok, {format_pattern(), keyword()}} | {:error, term()}
Gets the effective format pattern for a given value and context.
Evaluates conditional rules against the provided value and returns the appropriate format pattern and options.
Parameters
spec- The compiled format specificationvalue- The value to formatcontext- Additional context for condition evaluation
Examples
spec = compiled_conditional_spec()
{:ok, {pattern, opts}} = AshReports.FormatSpecification.get_effective_format(
spec,
1500,
%{locale: "en"}
)
@spec new( format_spec_name(), keyword() ) :: format_spec()
Creates a new format specification with the given name and configuration.
Parameters
name- Unique identifier for the format specificationoptions- Configuration options for the specification
Options
:pattern- The base format pattern string:locale_aware- Whether the format should respect locale settings (default: true):type- Expected data type (:number, :currency, :date, :text, :percentage):fallback- Fallback format specification or pattern:cache- Whether to cache compiled format (default: true)
Examples
iex> spec = AshReports.FormatSpecification.new(:custom_number, pattern: "#,##0.00")
iex> spec.name
:custom_number
@spec set_default_pattern(format_spec(), format_pattern()) :: format_spec()
Sets the default formatting pattern for a specification.
The default pattern is used when no conditional rules match or when no conditions are defined.
Parameters
spec- The format specification to modifypattern- The default format pattern string
Examples
spec = AshReports.FormatSpecification.new(:my_format)
|> AshReports.FormatSpecification.set_default_pattern("#,##0.00")
@spec validate(format_spec()) :: :ok | {:error, term()}
Validates a format specification without compiling it.
Performs syntax and semantic validation of format patterns, conditions, and options without the overhead of full compilation.
Parameters
spec- The format specification to validate
Examples
spec = AshReports.FormatSpecification.new(:test, pattern: "invalid{pattern")
AshReports.FormatSpecification.validate(spec)
# => {:error, "Invalid pattern syntax..."}