- Add scoped logger (pugz/runtime) for better log filtering
- Add warnings when mixin not found
- Add warnings for mixin attribute failures
- Add warnings for mixin directory/file lookup failures
- Add warnings for mixin parse/tokenize failures
- Use 'action first, then reason' pattern in all log messages
The loadMixinFromDir function used openDirAbsolute which requires an
absolute path, but ViewEngine passes a relative path for mixins_dir.
This caused a panic when a mixin call couldn't find the mixin in the
current template.
Fix: Check if mixins_dir is absolute and use the appropriate method:
- std.fs.openDirAbsolute() for absolute paths
- std.fs.cwd().openDir() for relative paths
Features:
- Fix string concatenation in attribute values (e.g., class="btn btn-" + type)
- Lexer now properly captures full expressions with operators
- Runtime evaluates expressions for class attributes
ViewEngine improvements:
- Change mixin loading from eager to lazy (on-demand)
- Mixins are now loaded from mixins directory only when first called
- Template-defined mixins take precedence over directory mixins
Benchmarks:
- Add src/benchmark.zig with three template complexity levels
- Simple: ~150k renders/sec, 6KB memory
- Medium: ~70k renders/sec, 45KB memory
- Complex: ~32k renders/sec, 94KB memory
- Memory leak detection confirms no leaks
Documentation:
- Update CLAUDE.md with lazy mixin loading details
- Document mixin resolution order
- Lexer now emits a single token for the entire expression (e.g., "btn btn-" + type)
- Runtime evaluateExpression now handles + operator for string concatenation
- Added findConcatOperator to safely find operators outside quotes/brackets