# CLAUDE.md This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository. ## Project Purpose Pugz is a Pug-like HTML template engine written in Zig 0.15.2. It implements Pug 3 syntax for indentation-based HTML templating with a focus on server-side rendering. ## Build Commands - `zig build` - Build the project (output in `zig-out/`) - `zig build run` - Build and run the executable - `zig build test` - Run all tests (113 tests currently) ## Architecture Overview The template engine follows a classic compiler pipeline: ``` Source → Lexer → Tokens → Parser → AST → Runtime → HTML ``` ### Core Modules | Module | Purpose | |--------|---------| | **src/lexer.zig** | Tokenizes Pug source into tokens. Handles indentation tracking, raw text blocks, interpolation. | | **src/parser.zig** | Converts token stream into AST. Handles nesting via indent/dedent tokens. | | **src/ast.zig** | AST node definitions (Element, Text, Conditional, Each, Mixin, etc.) | | **src/runtime.zig** | Evaluates AST with data context, produces final HTML. Handles variable interpolation, conditionals, loops, mixins. | | **src/codegen.zig** | Static HTML generation (without runtime evaluation). Outputs placeholders for dynamic content. | | **src/root.zig** | Public library API - exports `renderTemplate()` and core types. | | **src/main.zig** | CLI executable example. | ### Test Files - **src/tests/general_test.zig** - Comprehensive integration tests for all features ## Memory Management **Important**: The runtime is designed to work with `ArenaAllocator`: ```zig var arena = std.heap.ArenaAllocator.init(allocator); defer arena.deinit(); // Frees all template memory at once const html = try pugz.renderTemplate(arena.allocator(), template, data); ``` This pattern is recommended because template rendering creates many small allocations that are all freed together after the response is sent. ## Key Implementation Details ### Lexer State Machine The lexer tracks several states for handling complex syntax: - `in_raw_block` / `raw_block_indent` / `raw_block_started` - For dot block text (e.g., `script.`) - `indent_stack` - Stack-based indent/dedent token generation ### Token Types Key tokens: `tag`, `class`, `id`, `lparen`, `rparen`, `attr_name`, `attr_value`, `text`, `interp_start`, `interp_end`, `indent`, `dedent`, `dot_block`, `pipe_text`, `literal_html`, `self_close`, `mixin_call`, etc. ### AST Node Types - `element` - HTML elements with tag, classes, id, attributes, children - `text` - Text with segments (literal, escaped interpolation, unescaped interpolation, tag interpolation) - `conditional` - if/else if/else/unless branches - `each` - Iteration with value, optional index, else branch - `mixin_def` / `mixin_call` - Mixin definitions and invocations - `block` - Named blocks for template inheritance - `include` / `extends` - File inclusion and inheritance - `raw_text` - Literal HTML or text blocks ### Runtime Value System ```zig pub const Value = union(enum) { null, bool: bool, int: i64, float: f64, string: []const u8, array: []const Value, object: std.StringHashMapUnmanaged(Value), }; ``` The `toValue()` function converts Zig structs to runtime Values automatically. ## Supported Pug Features ### Tags & Nesting ```pug div h1 Title p Paragraph ``` ### Classes & IDs (shorthand) ```pug div#main.container.active .box // defaults to div #sidebar // defaults to div ``` ### Attributes ```pug a(href="/link" target="_blank") Click input(type="checkbox" checked) div(style={color: 'red'}) div(class=['foo', 'bar']) button(disabled=false) // omitted when false button(disabled=true) // disabled="disabled" ``` ### Text & Interpolation ```pug p Hello #{name} // escaped interpolation p Hello !{rawHtml} // unescaped interpolation p= variable // buffered code (escaped) p!= rawVariable // buffered code (unescaped) | Piped text line p. Multi-line text block
Literal HTML
// passed through as-is ``` ### Tag Interpolation ```pug p This is #[em emphasized] text p Click #[a(href="/") here] to continue ``` ### Block Expansion ```pug a: img(src="logo.png") // colon for inline nesting ``` ### Explicit Self-Closing ```pug foo/ // renders as