refactor: replace ArrayListUnmanaged with ArrayList per Zig 0.15 standards

- Renamed std.ArrayListUnmanaged to std.ArrayList across all source files
- Updated CLAUDE.md with Zig version standards rule
- Removed debug print from mixin test
- No API changes (allocator still passed to methods)
This commit is contained in:
2026-01-29 22:50:52 +05:30
parent b53aa16010
commit 2c98dab144
29 changed files with 122 additions and 124 deletions

View File

@@ -85,7 +85,7 @@ pub const CompilerError = error{
pub const Compiler = struct {
allocator: Allocator,
options: CompilerOptions,
output: std.ArrayListUnmanaged(u8),
output: std.ArrayList(u8),
indent_level: usize = 0,
has_doctype: bool = false,
has_tag: bool = false,

View File

@@ -233,7 +233,7 @@ fn compileSingleFile(
}
fn findPugFiles(allocator: mem.Allocator, dir_path: []const u8) ![][]const u8 {
var results: std.ArrayListUnmanaged([]const u8) = .{};
var results: std.ArrayList([]const u8) = .{};
errdefer {
for (results.items) |item| allocator.free(item);
results.deinit(allocator);
@@ -243,7 +243,7 @@ fn findPugFiles(allocator: mem.Allocator, dir_path: []const u8) ![][]const u8 {
return results.toOwnedSlice(allocator);
}
fn findPugFilesRecursive(allocator: mem.Allocator, dir_path: []const u8, results: *std.ArrayListUnmanaged([]const u8)) !void {
fn findPugFilesRecursive(allocator: mem.Allocator, dir_path: []const u8, results: *std.ArrayList([]const u8)) !void {
var dir = try fs.cwd().openDir(dir_path, .{ .iterate = true });
defer dir.close();
@@ -277,7 +277,7 @@ fn makeTemplateName(allocator: mem.Allocator, path: []const u8) ![]const u8 {
else
path;
var result: std.ArrayListUnmanaged(u8) = .{};
var result: std.ArrayList(u8) = .{};
defer result.deinit(allocator);
for (without_ext) |c| {
@@ -298,7 +298,7 @@ fn makeFlatFileName(allocator: mem.Allocator, path: []const u8) ![]const u8 {
else
path;
var result: std.ArrayListUnmanaged(u8) = .{};
var result: std.ArrayList(u8) = .{};
defer result.deinit(allocator);
for (without_ext) |c| {
@@ -315,14 +315,14 @@ fn makeFlatFileName(allocator: mem.Allocator, path: []const u8) ![]const u8 {
}
fn generateRootZig(allocator: mem.Allocator, output_dir: []const u8, template_map: *std.StringHashMap([]const u8)) !void {
var output: std.ArrayListUnmanaged(u8) = .{};
var output: std.ArrayList(u8) = .{};
defer output.deinit(allocator);
try output.appendSlice(allocator, "// Auto-generated by Pugz build step\n");
try output.appendSlice(allocator, "// This file exports all compiled templates\n\n");
// Sort template names
var names: std.ArrayListUnmanaged([]const u8) = .{};
var names: std.ArrayList([]const u8) = .{};
defer names.deinit(allocator);
var iter = template_map.keyIterator();

View File

@@ -1,7 +1,7 @@
const std = @import("std");
const mem = std.mem;
const Allocator = std.mem.Allocator;
const ArrayListUnmanaged = std.ArrayListUnmanaged;
const ArrayList = std.ArrayList;
// ============================================================================
// Pug Error - Error formatting with source context
@@ -47,7 +47,7 @@ pub const PugError = struct {
/// Format as JSON-like structure for serialization
pub fn toJson(self: *const PugError, allocator: Allocator) ![]const u8 {
var result: ArrayListUnmanaged(u8) = .{};
var result: ArrayList(u8) = .{};
errdefer result.deinit(allocator);
try result.appendSlice(allocator, "{\"code\":\"");
@@ -76,7 +76,7 @@ pub const PugError = struct {
};
/// Append JSON-escaped string to result
fn appendJsonEscaped(allocator: Allocator, result: *ArrayListUnmanaged(u8), s: []const u8) !void {
fn appendJsonEscaped(allocator: Allocator, result: *ArrayList(u8), s: []const u8) !void {
for (s) |c| {
switch (c) {
'"' => try result.appendSlice(allocator, "\\\""),
@@ -150,7 +150,7 @@ fn formatErrorMessage(
) ![]const u8 {
_ = code; // Code is embedded in PugError struct
var result: ArrayListUnmanaged(u8) = .{};
var result: ArrayList(u8) = .{};
errdefer result.deinit(allocator);
// Header: filename:line:column or Pug:line:column
@@ -231,7 +231,7 @@ fn formatErrorMessage(
/// Split source into lines (handles \n, \r\n, \r)
fn splitLines(allocator: Allocator, src: []const u8) ![][]const u8 {
var lines: ArrayListUnmanaged([]const u8) = .{};
var lines: ArrayList([]const u8) = .{};
errdefer lines.deinit(allocator);
var start: usize = 0;

View File

@@ -180,13 +180,13 @@ pub const Token = struct {
};
// ============================================================================
// Character Parser State (simplified) - Zig 0.15 style with ArrayListUnmanaged
// Character Parser State (simplified) - Zig 0.15 style with ArrayList
// ============================================================================
const BracketType = enum { paren, brace, bracket };
const CharParserState = struct {
nesting_stack: std.ArrayListUnmanaged(BracketType) = .{},
nesting_stack: std.ArrayList(BracketType) = .{},
in_string: bool = false,
string_char: ?u8 = null,
in_template: bool = false,
@@ -320,7 +320,7 @@ const BracketExpressionResult = struct {
};
// ============================================================================
// Lexer - Zig 0.15 style with ArrayListUnmanaged
// Lexer - Zig 0.15 style with ArrayList
// ============================================================================
pub const Lexer = struct {
@@ -332,10 +332,10 @@ pub const Lexer = struct {
interpolated: bool,
lineno: usize,
colno: usize,
indent_stack: std.ArrayListUnmanaged(usize) = .{},
indent_stack: std.ArrayList(usize) = .{},
indent_re_type: ?IndentType = null,
interpolation_allowed: bool,
tokens: std.ArrayListUnmanaged(Token) = .{},
tokens: std.ArrayList(Token) = .{},
ended: bool,
last_error: ?LexerError = null,
@@ -359,7 +359,7 @@ pub const Lexer = struct {
}
// Normalize line endings
var normalized: std.ArrayListUnmanaged(u8) = .{};
var normalized: std.ArrayList(u8) = .{};
errdefer normalized.deinit(allocator);
var i: usize = 0;
@@ -378,7 +378,7 @@ pub const Lexer = struct {
}
}
var indent_stack: std.ArrayListUnmanaged(usize) = .{};
var indent_stack: std.ArrayList(usize) = .{};
try indent_stack.append(allocator, 0);
const input_slice = try normalized.toOwnedSlice(allocator);
@@ -1349,7 +1349,7 @@ pub const Lexer = struct {
/// Validates that brackets in an expression are balanced
fn validateExpressionBrackets(self: *Lexer, expr: []const u8) bool {
var bracket_stack = std.ArrayListUnmanaged(u8){};
var bracket_stack = std.ArrayList(u8){};
defer bracket_stack.deinit(self.allocator);
var in_string: u8 = 0;
@@ -2309,8 +2309,8 @@ pub const Lexer = struct {
self.tokens.append(self.allocator, start_token) catch return false;
var string_ptr: usize = 0;
var tokens_list: std.ArrayListUnmanaged([]const u8) = .{};
var token_indent_list: std.ArrayListUnmanaged(bool) = .{};
var tokens_list: std.ArrayList([]const u8) = .{};
var token_indent_list: std.ArrayList(bool) = .{};
defer tokens_list.deinit(self.allocator);
defer token_indent_list.deinit(self.allocator);
@@ -2451,7 +2451,7 @@ pub const Lexer = struct {
var in_string: u8 = 0;
// Track bracket stack - inside #[...] you can have (...) and {...} for attrs/code
var bracket_stack = std.ArrayListUnmanaged(u8){};
var bracket_stack = std.ArrayList(u8){};
defer bracket_stack.deinit(self.allocator);
bracket_stack.append(self.allocator, '[') catch return;

View File

@@ -102,10 +102,10 @@ pub fn link(allocator: Allocator, ast: *Node) LinkerError!LinkerResult {
// Handle extends
if (extends_node) |ext_node| {
// Get mixins and expected blocks from current template
var mixins = std.ArrayListUnmanaged(*Node){};
var mixins = std.ArrayList(*Node){};
defer mixins.deinit(allocator);
var expected_blocks = std.ArrayListUnmanaged(*Node){};
var expected_blocks = std.ArrayList(*Node){};
defer expected_blocks.deinit(allocator);
try collectMixinsAndBlocks(allocator, result.ast, &mixins, &expected_blocks);
@@ -178,8 +178,8 @@ fn findDeclaredBlocks(allocator: Allocator, ast: *Node) LinkerError!BlockDefinit
fn collectMixinsAndBlocks(
allocator: Allocator,
ast: *Node,
mixins: *std.ArrayListUnmanaged(*Node),
expected_blocks: *std.ArrayListUnmanaged(*Node),
mixins: *std.ArrayList(*Node),
expected_blocks: *std.ArrayList(*Node),
) LinkerError!void {
for (ast.nodes.items) |node| {
switch (node.type) {

View File

@@ -357,7 +357,7 @@ pub fn pathJoin(allocator: Allocator, base: []const u8, relative: []const u8) ![
const base_dir = dirname(base);
// Handle .. and . components
var result = std.ArrayListUnmanaged(u8){};
var result = std.ArrayList(u8){};
errdefer result.deinit(allocator);
try result.appendSlice(allocator, base_dir);

View File

@@ -289,7 +289,7 @@ fn substituteArgs(
}
// Perform substitution
var result = std.ArrayListUnmanaged(u8){};
var result = std.ArrayList(u8){};
errdefer result.deinit(allocator);
var i: usize = 0;
@@ -335,7 +335,7 @@ fn evaluateStringConcat(allocator: Allocator, expr: []const u8) ![]const u8 {
// Check if there's a + operator (string concat)
_ = mem.indexOf(u8, expr, " + ") orelse return expr;
var result = std.ArrayListUnmanaged(u8){};
var result = std.ArrayList(u8){};
errdefer result.deinit(allocator);
var remaining = expr;
@@ -386,7 +386,7 @@ fn bindArguments(
bindings: *std.StringHashMapUnmanaged([]const u8),
) MixinError!void {
// Parse parameter names from definition: "text, type" or "text, type='primary'"
var param_names = std.ArrayListUnmanaged([]const u8){};
var param_names = std.ArrayList([]const u8){};
defer param_names.deinit(allocator);
var param_iter = mem.splitSequence(u8, params, ",");
@@ -409,7 +409,7 @@ fn bindArguments(
}
// Parse argument values from call: "'Click', 'primary'" or "text='Click'"
var arg_values = std.ArrayListUnmanaged([]const u8){};
var arg_values = std.ArrayList([]const u8){};
defer arg_values.deinit(allocator);
// Simple argument parsing - split by comma but respect quotes
@@ -589,12 +589,6 @@ test "bindArguments - with default value in param" {
// This is how it appears: params have default, args are the call args
try bindArguments(allocator, "text, type=\"primary\"", "\"Click Me\", \"primary\"", &bindings);
std.debug.print("\nBindings:\n", .{});
var iter = bindings.iterator();
while (iter.next()) |entry| {
std.debug.print(" {s} = '{s}'\n", .{ entry.key_ptr.*, entry.value_ptr.* });
}
try std.testing.expectEqualStrings("Click Me", bindings.get("text").?);
try std.testing.expectEqualStrings("primary", bindings.get("type").?);
}

View File

@@ -110,7 +110,7 @@ pub const Node = struct {
filename: ?[]const u8 = null,
// Block fields
nodes: std.ArrayListUnmanaged(*Node) = .{},
nodes: std.ArrayList(*Node) = .{},
// NamedBlock additional fields
name: ?[]const u8 = null, // Also used for Tag, Mixin, Filter
@@ -118,8 +118,8 @@ pub const Node = struct {
// Tag fields
self_closing: bool = false,
attrs: std.ArrayListUnmanaged(Attribute) = .{},
attribute_blocks: std.ArrayListUnmanaged(AttributeBlock) = .{},
attrs: std.ArrayList(Attribute) = .{},
attribute_blocks: std.ArrayList(AttributeBlock) = .{},
is_inline: bool = false,
text_only: bool = false,
self_closing_allowed: bool = false,
@@ -150,7 +150,7 @@ pub const Node = struct {
file: ?FileReference = null,
// Include fields
filters: std.ArrayListUnmanaged(*Node) = .{},
filters: std.ArrayList(*Node) = .{},
// InterpolatedTag fields
expr: ?[]const u8 = null,
@@ -247,7 +247,7 @@ pub const Parser = struct {
allocator: Allocator,
tokens: []const Token,
pos: usize = 0,
deferred: std.ArrayListUnmanaged(Token) = .{},
deferred: std.ArrayList(Token) = .{},
filename: ?[]const u8 = null,
src: ?[]const u8 = null,
in_mixin: usize = 0,
@@ -475,7 +475,7 @@ pub const Parser = struct {
fn parseText(self: *Parser, allow_block: bool) !*Node {
const lineno = self.peek().loc.start.line;
var tags = std.ArrayListUnmanaged(*Node){};
var tags = std.ArrayList(*Node){};
defer tags.deinit(self.allocator);
while (true) {
@@ -548,8 +548,8 @@ pub const Parser = struct {
}
}
fn parseTextHtml(self: *Parser) !std.ArrayListUnmanaged(*Node) {
var nodes = std.ArrayListUnmanaged(*Node){};
fn parseTextHtml(self: *Parser) !std.ArrayList(*Node) {
var nodes = std.ArrayList(*Node){};
var current_node: ?*Node = null;
while (true) {
@@ -922,7 +922,7 @@ pub const Parser = struct {
const line = tok.loc.start.line;
const column = tok.loc.start.column;
var text = std.ArrayListUnmanaged(u8){};
var text = std.ArrayList(u8){};
defer text.deinit(self.allocator);
if (self.peek().type == .start_pipeless_text) {
@@ -1095,7 +1095,7 @@ pub const Parser = struct {
fn parseIncludeFilter(self: *Parser) !*Node {
const tok = try self.expect(.filter);
var filter_attrs = std.ArrayListUnmanaged(Attribute){};
var filter_attrs = std.ArrayList(Attribute){};
if (self.peek().type == .start_attributes) {
filter_attrs = try self.attrs(null);
@@ -1115,7 +1115,7 @@ pub const Parser = struct {
fn parseFilter(self: *Parser) !*Node {
const tok = try self.expect(.filter);
var filter_attrs = std.ArrayListUnmanaged(Attribute){};
var filter_attrs = std.ArrayList(Attribute){};
if (self.peek().type == .start_attributes) {
filter_attrs = try self.attrs(null);
@@ -1483,11 +1483,11 @@ pub const Parser = struct {
fn tag_(self: *Parser, tag: *Node, self_closing_allowed: bool) !void {
var seen_attrs = false;
var attribute_names = std.ArrayListUnmanaged([]const u8){};
var attribute_names = std.ArrayList([]const u8){};
defer attribute_names.deinit(self.allocator);
// Collect class values to merge into single attribute
var class_values = std.ArrayListUnmanaged([]const u8){};
var class_values = std.ArrayList([]const u8){};
defer class_values.deinit(self.allocator);
var class_line: usize = 0;
var class_column: usize = 0;
@@ -1689,10 +1689,10 @@ pub const Parser = struct {
}
}
fn attrs(self: *Parser, attribute_names: ?*std.ArrayListUnmanaged([]const u8)) !std.ArrayListUnmanaged(Attribute) {
fn attrs(self: *Parser, attribute_names: ?*std.ArrayList([]const u8)) !std.ArrayList(Attribute) {
_ = try self.expect(.start_attributes);
var result = std.ArrayListUnmanaged(Attribute){};
var result = std.ArrayList(Attribute){};
var tok = self.advance();
while (tok.type == .attribute) {

View File

@@ -1,7 +1,7 @@
const std = @import("std");
const mem = std.mem;
const Allocator = std.mem.Allocator;
const ArrayListUnmanaged = std.ArrayListUnmanaged;
const ArrayList = std.ArrayList;
// ============================================================================
// Pug Runtime - HTML generation utilities
@@ -45,7 +45,7 @@ pub fn escape(allocator: Allocator, html: []const u8) ![]const u8 {
return try allocator.dupe(u8, html);
}
var result: ArrayListUnmanaged(u8) = .{};
var result: ArrayList(u8) = .{};
errdefer result.deinit(allocator);
for (html) |c| {
@@ -84,7 +84,7 @@ pub fn style(allocator: Allocator, val: StyleValue) ![]const u8 {
return try allocator.dupe(u8, s);
},
.object => |props| {
var result: ArrayListUnmanaged(u8) = .{};
var result: ArrayList(u8) = .{};
errdefer result.deinit(allocator);
for (props) |prop| {
@@ -111,7 +111,7 @@ pub const AttrValue = union(enum) {
/// Returns empty string for false/null values.
/// For true values, returns terse form " key" or full form " key="key"".
pub fn attr(allocator: Allocator, key: []const u8, val: AttrValue, escaped: bool, terse: bool) ![]const u8 {
var result: ArrayListUnmanaged(u8) = .{};
var result: ArrayList(u8) = .{};
errdefer result.deinit(allocator);
try appendAttr(allocator, &result, key, val, escaped, terse);
if (result.items.len == 0) {
@@ -122,7 +122,7 @@ pub fn attr(allocator: Allocator, key: []const u8, val: AttrValue, escaped: bool
/// Append attribute directly to output buffer - avoids intermediate allocations
/// This is the preferred method for rendering attributes in hot paths
pub fn appendAttr(allocator: Allocator, output: *ArrayListUnmanaged(u8), key: []const u8, val: AttrValue, escaped: bool, terse: bool) !void {
pub fn appendAttr(allocator: Allocator, output: *ArrayList(u8), key: []const u8, val: AttrValue, escaped: bool, terse: bool) !void {
switch (val) {
.none => return,
.boolean => |b| {
@@ -186,7 +186,7 @@ pub const ClassCondition = struct {
/// Arrays are flattened, objects include keys with truthy values.
/// Optimized to minimize allocations by writing directly to result buffer.
pub fn classes(allocator: Allocator, val: ClassValue, escaping: ?[]const bool) ![]const u8 {
var result: ArrayListUnmanaged(u8) = .{};
var result: ArrayList(u8) = .{};
errdefer result.deinit(allocator);
try classesInternal(allocator, val, escaping, &result, 0);
@@ -204,7 +204,7 @@ fn classesInternal(
allocator: Allocator,
val: ClassValue,
escaping: ?[]const bool,
result: *ArrayListUnmanaged(u8),
result: *ArrayList(u8),
depth: usize,
) !void {
switch (val) {
@@ -236,7 +236,7 @@ fn classesInternal(
const had_content = start_len > 0;
// Temporarily collect the class string
var temp: ArrayListUnmanaged(u8) = .{};
var temp: ArrayList(u8) = .{};
defer temp.deinit(allocator);
try classesInternal(allocator, item, null, &temp, depth + 1);
@@ -256,7 +256,7 @@ fn classesInternal(
/// Append escaped HTML directly to result buffer (avoids intermediate allocation)
/// Public for use by codegen and other modules
pub fn appendEscaped(allocator: Allocator, result: *ArrayListUnmanaged(u8), html: []const u8) !void {
pub fn appendEscaped(allocator: Allocator, result: *ArrayList(u8), html: []const u8) !void {
for (html) |c| {
if (escapeChar(c)) |escaped| {
try result.appendSlice(allocator, escaped);
@@ -350,7 +350,7 @@ pub fn isHtmlEntity(str: []const u8) bool {
/// Escape for text content - escapes < > & (NOT quotes)
/// Preserves existing HTML entities like &#8217; or &amp;
/// Shared across codegen.zig and template.zig.
pub fn appendTextEscaped(allocator: Allocator, output: *ArrayListUnmanaged(u8), str: []const u8) Allocator.Error!void {
pub fn appendTextEscaped(allocator: Allocator, output: *ArrayList(u8), str: []const u8) Allocator.Error!void {
var i: usize = 0;
while (i < str.len) {
const c = str[i];
@@ -396,7 +396,7 @@ pub const AttrEntry = struct {
/// Render multiple attributes.
/// Class attributes are processed specially and placed first.
pub fn attrs(allocator: Allocator, entries: []const AttrEntry, terse: bool) ![]const u8 {
var result: ArrayListUnmanaged(u8) = .{};
var result: ArrayList(u8) = .{};
errdefer result.deinit(allocator);
// First pass: find and render class attribute
@@ -459,7 +459,7 @@ pub const MergedValue = struct {
key: []const u8,
value: MergeValue,
allocator: Allocator,
owned_strings: ArrayListUnmanaged([]const u8),
owned_strings: ArrayList([]const u8),
pub fn deinit(self: *MergedValue) void {
for (self.owned_strings.items) |s| {
@@ -474,7 +474,7 @@ fn ensureTrailingSemicolon(allocator: Allocator, s: []const u8) ![]const u8 {
if (s.len == 0) return try allocator.dupe(u8, "");
if (s[s.len - 1] == ';') return try allocator.dupe(u8, s);
var result: ArrayListUnmanaged(u8) = .{};
var result: ArrayList(u8) = .{};
errdefer result.deinit(allocator);
try result.appendSlice(allocator, s);
try result.append(allocator, ';');
@@ -495,9 +495,9 @@ fn styleToString(allocator: Allocator, val: StyleValue) ![]const u8 {
/// Merged attributes result with O(1) lookups for class/style
pub const MergedAttrs = struct {
allocator: Allocator,
entries: ArrayListUnmanaged(MergedAttrEntry),
owned_strings: ArrayListUnmanaged([]const u8),
owned_class_arrays: ArrayListUnmanaged([][]const u8),
entries: ArrayList(MergedAttrEntry),
owned_strings: ArrayList([]const u8),
owned_class_arrays: ArrayList([][]const u8),
// O(1) index tracking for special keys
class_idx: ?usize = null,
style_idx: ?usize = null,
@@ -751,7 +751,7 @@ fn mergeStyleValue(result: *MergedAttrs, idx: usize, value: MergedAttrValue) !vo
const s2 = try ensureTrailingSemicolon(allocator, s);
defer allocator.free(s2);
var combined: ArrayListUnmanaged(u8) = .{};
var combined: ArrayList(u8) = .{};
errdefer combined.deinit(allocator);
try combined.appendSlice(allocator, s1);
try combined.appendSlice(allocator, s2);
@@ -842,7 +842,7 @@ pub const PugError = struct {
};
fn formatErrorMessage(allocator: Allocator, err_message: []const u8, filename: ?[]const u8, line: usize, src: []const u8) ![]const u8 {
var result: ArrayListUnmanaged(u8) = .{};
var result: ArrayList(u8) = .{};
errdefer result.deinit(allocator);
// Add filename and line

View File

@@ -44,7 +44,7 @@ pub const StripCommentsError = error{
// ============================================================================
pub const StripCommentsResult = struct {
tokens: std.ArrayListUnmanaged(Token),
tokens: std.ArrayList(Token),
err: ?PugError = null,
pub fn deinit(self: *StripCommentsResult, allocator: Allocator) void {

View File

@@ -97,7 +97,7 @@ pub fn renderWithData(allocator: Allocator, source: []const u8, data: anytype) !
/// Render a pre-parsed AST with data. Use this for better performance when
/// rendering the same template multiple times - parse once, render many.
pub fn renderAst(allocator: Allocator, ast: *Node, data: anytype) ![]const u8 {
var output = std.ArrayListUnmanaged(u8){};
var output = std.ArrayList(u8){};
errdefer output.deinit(allocator);
// Detect doctype to set terse mode
@@ -122,7 +122,7 @@ pub fn renderAstWithMixins(allocator: Allocator, ast: *Node, data: anytype, regi
/// Render a pre-parsed AST with data, mixin registry, and render options.
pub fn renderAstWithMixinsAndOptions(allocator: Allocator, ast: *Node, data: anytype, registry: *const MixinRegistry, options: RenderOptions) ![]const u8 {
var output = std.ArrayListUnmanaged(u8){};
var output = std.ArrayList(u8){};
errdefer output.deinit(allocator);
// Detect doctype to set terse mode
@@ -213,14 +213,14 @@ fn detectDoctype(node: *Node, ctx: *RenderContext) void {
const whitespace_sensitive_tags = runtime.whitespace_sensitive_tags;
/// Write indentation (two spaces per level)
fn writeIndent(allocator: Allocator, output: *std.ArrayListUnmanaged(u8), level: u32) Allocator.Error!void {
fn writeIndent(allocator: Allocator, output: *std.ArrayList(u8), level: u32) Allocator.Error!void {
var i: u32 = 0;
while (i < level) : (i += 1) {
try output.appendSlice(allocator, " ");
}
}
fn renderNode(allocator: Allocator, output: *std.ArrayListUnmanaged(u8), node: *Node, data: anytype, ctx: *const RenderContext) Allocator.Error!void {
fn renderNode(allocator: Allocator, output: *std.ArrayList(u8), node: *Node, data: anytype, ctx: *const RenderContext) Allocator.Error!void {
switch (node.type) {
.Block, .NamedBlock => {
for (node.nodes.items) |child| {
@@ -251,7 +251,7 @@ fn renderNode(allocator: Allocator, output: *std.ArrayListUnmanaged(u8), node: *
}
}
fn renderTag(allocator: Allocator, output: *std.ArrayListUnmanaged(u8), tag: *Node, data: anytype, ctx: *const RenderContext) Allocator.Error!void {
fn renderTag(allocator: Allocator, output: *std.ArrayList(u8), tag: *Node, data: anytype, ctx: *const RenderContext) Allocator.Error!void {
const name = tag.name orelse "div";
const is_whitespace_sensitive = whitespace_sensitive_tags.has(name);
@@ -393,13 +393,13 @@ fn evaluateAttrValue(allocator: Allocator, val: ?[]const u8, data: anytype) !run
return .{ .string = v };
}
fn renderText(allocator: Allocator, output: *std.ArrayListUnmanaged(u8), text: *Node, data: anytype) Allocator.Error!void {
fn renderText(allocator: Allocator, output: *std.ArrayList(u8), text: *Node, data: anytype) Allocator.Error!void {
if (text.val) |val| {
try processInterpolation(allocator, output, val, false, data);
}
}
fn renderCode(allocator: Allocator, output: *std.ArrayListUnmanaged(u8), code: *Node, data: anytype, ctx: *const RenderContext) Allocator.Error!void {
fn renderCode(allocator: Allocator, output: *std.ArrayList(u8), code: *Node, data: anytype, ctx: *const RenderContext) Allocator.Error!void {
if (code.buffer) {
if (code.val) |val| {
// Check if it's a string literal (quoted)
@@ -441,7 +441,7 @@ fn renderCode(allocator: Allocator, output: *std.ArrayListUnmanaged(u8), code: *
}
/// Render mixin definition or call
fn renderMixin(allocator: Allocator, output: *std.ArrayListUnmanaged(u8), node: *Node, data: anytype, ctx: *const RenderContext) Allocator.Error!void {
fn renderMixin(allocator: Allocator, output: *std.ArrayList(u8), node: *Node, data: anytype, ctx: *const RenderContext) Allocator.Error!void {
// Mixin definitions are skipped (only mixin calls render)
if (!node.call) return;
@@ -494,7 +494,7 @@ fn bindMixinArguments(
bindings: *std.StringHashMapUnmanaged([]const u8),
) !void {
// Parse parameter names from definition: "text, type" or "text, type='primary'"
var param_names = std.ArrayListUnmanaged([]const u8){};
var param_names = std.ArrayList([]const u8){};
defer param_names.deinit(allocator);
var param_iter = std.mem.splitSequence(u8, params, ",");
@@ -517,7 +517,7 @@ fn bindMixinArguments(
}
// Parse argument values from call: "'Click', 'primary'" or "text='Click'"
var arg_values = std.ArrayListUnmanaged([]const u8){};
var arg_values = std.ArrayList([]const u8){};
defer arg_values.deinit(allocator);
// Simple argument parsing - split by comma but respect quotes
@@ -572,7 +572,7 @@ fn stripQuotes(val: []const u8) []const u8 {
return val;
}
fn renderEach(allocator: Allocator, output: *std.ArrayListUnmanaged(u8), each: *Node, data: anytype, ctx: *const RenderContext) Allocator.Error!void {
fn renderEach(allocator: Allocator, output: *std.ArrayList(u8), each: *Node, data: anytype, ctx: *const RenderContext) Allocator.Error!void {
const collection_name = each.obj orelse return;
const item_name = each.val orelse "item";
_ = item_name;
@@ -623,7 +623,7 @@ fn renderEach(allocator: Allocator, output: *std.ArrayListUnmanaged(u8), each: *
}
}
fn renderNodeWithItem(allocator: Allocator, output: *std.ArrayListUnmanaged(u8), node: *Node, data: anytype, item: []const u8, ctx: *const RenderContext) Allocator.Error!void {
fn renderNodeWithItem(allocator: Allocator, output: *std.ArrayList(u8), node: *Node, data: anytype, item: []const u8, ctx: *const RenderContext) Allocator.Error!void {
switch (node.type) {
.Block, .NamedBlock => {
for (node.nodes.items) |child| {
@@ -649,7 +649,7 @@ fn renderNodeWithItem(allocator: Allocator, output: *std.ArrayListUnmanaged(u8),
}
}
fn renderTagWithItem(allocator: Allocator, output: *std.ArrayListUnmanaged(u8), tag: *Node, data: anytype, item: []const u8, ctx: *const RenderContext) Allocator.Error!void {
fn renderTagWithItem(allocator: Allocator, output: *std.ArrayList(u8), tag: *Node, data: anytype, item: []const u8, ctx: *const RenderContext) Allocator.Error!void {
const name = tag.name orelse "div";
try output.appendSlice(allocator, "<");
@@ -698,14 +698,14 @@ fn renderTagWithItem(allocator: Allocator, output: *std.ArrayListUnmanaged(u8),
}
}
fn renderTextWithItem(allocator: Allocator, output: *std.ArrayListUnmanaged(u8), text: *Node, item: []const u8) Allocator.Error!void {
fn renderTextWithItem(allocator: Allocator, output: *std.ArrayList(u8), text: *Node, item: []const u8) Allocator.Error!void {
if (text.val) |val| {
try runtime.appendEscaped(allocator, output, val);
_ = item;
}
}
fn processInterpolationWithItem(allocator: Allocator, output: *std.ArrayListUnmanaged(u8), text: []const u8, escape: bool, data: anytype, item: []const u8) Allocator.Error!void {
fn processInterpolationWithItem(allocator: Allocator, output: *std.ArrayList(u8), text: []const u8, escape: bool, data: anytype, item: []const u8) Allocator.Error!void {
_ = data;
var i: usize = 0;
while (i < text.len) {
@@ -740,7 +740,7 @@ fn processInterpolationWithItem(allocator: Allocator, output: *std.ArrayListUnma
}
}
fn renderComment(allocator: Allocator, output: *std.ArrayListUnmanaged(u8), comment: *Node) Allocator.Error!void {
fn renderComment(allocator: Allocator, output: *std.ArrayList(u8), comment: *Node) Allocator.Error!void {
if (!comment.buffer) return;
try output.appendSlice(allocator, "<!--");
if (comment.val) |val| {
@@ -749,7 +749,7 @@ fn renderComment(allocator: Allocator, output: *std.ArrayListUnmanaged(u8), comm
try output.appendSlice(allocator, "-->");
}
fn renderBlockComment(allocator: Allocator, output: *std.ArrayListUnmanaged(u8), comment: *Node, data: anytype, ctx: *const RenderContext) Allocator.Error!void {
fn renderBlockComment(allocator: Allocator, output: *std.ArrayList(u8), comment: *Node, data: anytype, ctx: *const RenderContext) Allocator.Error!void {
if (!comment.buffer) return;
try output.appendSlice(allocator, "<!--");
if (comment.val) |val| {
@@ -765,7 +765,7 @@ fn renderBlockComment(allocator: Allocator, output: *std.ArrayListUnmanaged(u8),
// Import doctypes from runtime (shared with codegen)
const doctypes = runtime.doctypes;
fn renderDoctype(allocator: Allocator, output: *std.ArrayListUnmanaged(u8), doctype: *Node) Allocator.Error!void {
fn renderDoctype(allocator: Allocator, output: *std.ArrayList(u8), doctype: *Node) Allocator.Error!void {
if (doctype.val) |val| {
if (doctypes.get(val)) |dt| {
try output.appendSlice(allocator, dt);
@@ -781,7 +781,7 @@ fn renderDoctype(allocator: Allocator, output: *std.ArrayListUnmanaged(u8), doct
/// Process interpolation #{expr} in text
/// escape_quotes: true for attribute values (escape "), false for text content
fn processInterpolation(allocator: Allocator, output: *std.ArrayListUnmanaged(u8), text: []const u8, escape_quotes: bool, data: anytype) Allocator.Error!void {
fn processInterpolation(allocator: Allocator, output: *std.ArrayList(u8), text: []const u8, escape_quotes: bool, data: anytype) Allocator.Error!void {
var i: usize = 0;
while (i < text.len) {
if (i + 1 < text.len and text[i] == '#' and text[i + 1] == '{') {
@@ -867,7 +867,7 @@ fn getFieldValue(data: anytype, name: []const u8) ?[]const u8 {
/// Escape for text content - escapes < > & (NOT quotes)
/// Preserves existing HTML entities like &#8217;
/// Uses shared appendTextEscaped from runtime.zig.
fn appendTextEscaped(allocator: Allocator, output: *std.ArrayListUnmanaged(u8), str: []const u8) Allocator.Error!void {
fn appendTextEscaped(allocator: Allocator, output: *std.ArrayList(u8), str: []const u8) Allocator.Error!void {
try runtime.appendTextEscaped(allocator, output, str);
}

View File

@@ -7,7 +7,7 @@ const pugz = @import("pugz");
/// Normalizes HTML by removing indentation/formatting whitespace.
/// This allows comparing pretty vs non-pretty output.
pub fn normalizeHtml(allocator: std.mem.Allocator, html: []const u8) ![]const u8 {
var result = std.ArrayListUnmanaged(u8){};
var result = std.ArrayList(u8){};
var i: usize = 0;
var in_tag = false;
var last_was_space = false;

View File

@@ -97,7 +97,7 @@ const ParsedTokens = struct {
};
fn parseJsonTokens(allocator: std.mem.Allocator, json_content: []const u8) !ParsedTokens {
var tokens = std.ArrayListUnmanaged(Token){};
var tokens = std.ArrayList(Token){};
errdefer tokens.deinit(allocator);
// Use an arena allocator to keep JSON string data alive
@@ -257,8 +257,8 @@ const TokenTestCase = struct {
}
};
fn loadTokenTestCases(allocator: std.mem.Allocator, dir_path: []const u8) !std.ArrayListUnmanaged(TokenTestCase) {
var cases = std.ArrayListUnmanaged(TokenTestCase){};
fn loadTokenTestCases(allocator: std.mem.Allocator, dir_path: []const u8) !std.ArrayList(TokenTestCase) {
var cases = std.ArrayList(TokenTestCase){};
errdefer {
for (cases.items) |*c| c.deinit();
cases.deinit(allocator);

View File

@@ -20,7 +20,7 @@ pub fn main() !void {
defer dir.close();
// Collect .pug files
var files = std.ArrayListUnmanaged([]const u8){};
var files = std.ArrayList([]const u8){};
defer {
for (files.items) |f| allocator.free(f);
files.deinit(allocator);

View File

@@ -4,7 +4,7 @@
const std = @import("std");
/// Append HTML-escaped string to buffer
pub fn appendEscaped(buf: *std.ArrayListUnmanaged(u8), allocator: std.mem.Allocator, str: []const u8) !void {
pub fn appendEscaped(buf: *std.ArrayList(u8), allocator: std.mem.Allocator, str: []const u8) !void {
for (str) |c| {
switch (c) {
'&' => try buf.appendSlice(allocator, "&amp;"),
@@ -33,21 +33,21 @@ pub fn isTruthy(val: anytype) bool {
}
/// Append an integer value to buffer (formatted as decimal string)
pub fn appendInt(buf: *std.ArrayListUnmanaged(u8), allocator: std.mem.Allocator, value: anytype) !void {
pub fn appendInt(buf: *std.ArrayList(u8), allocator: std.mem.Allocator, value: anytype) !void {
var tmp: [32]u8 = undefined;
const str = std.fmt.bufPrint(&tmp, "{d}", .{value}) catch return;
try buf.appendSlice(allocator, str);
}
/// Append a float value to buffer (formatted with 2 decimal places)
pub fn appendFloat(buf: *std.ArrayListUnmanaged(u8), allocator: std.mem.Allocator, value: anytype) !void {
pub fn appendFloat(buf: *std.ArrayList(u8), allocator: std.mem.Allocator, value: anytype) !void {
var tmp: [64]u8 = undefined;
const str = std.fmt.bufPrint(&tmp, "{d:.2}", .{value}) catch return;
try buf.appendSlice(allocator, str);
}
/// Append any value to buffer (auto-detects type)
pub fn appendValue(buf: *std.ArrayListUnmanaged(u8), allocator: std.mem.Allocator, value: anytype) !void {
pub fn appendValue(buf: *std.ArrayList(u8), allocator: std.mem.Allocator, value: anytype) !void {
const T = @TypeOf(value);
switch (@typeInfo(T)) {
.int, .comptime_int => try appendInt(buf, allocator, value),

View File

@@ -239,14 +239,14 @@ fn copyHelpersZig(allocator: mem.Allocator, output_dir: []const u8) !void {
/// Generate root.zig that exports all compiled templates
fn generateRootZig(allocator: mem.Allocator, output_dir: []const u8, template_map: *std.StringHashMap([]const u8)) !void {
var output: std.ArrayListUnmanaged(u8) = .{};
var output: std.ArrayList(u8) = .{};
defer output.deinit(allocator);
try output.appendSlice(allocator, "// Auto-generated by pug-compile\n");
try output.appendSlice(allocator, "// This file exports all compiled templates\n\n");
// Sort template names for consistent output
var names: std.ArrayListUnmanaged([]const u8) = .{};
var names: std.ArrayList([]const u8) = .{};
defer names.deinit(allocator);
var iter = template_map.keyIterator();
@@ -298,7 +298,7 @@ fn generateRootZig(allocator: mem.Allocator, output_dir: []const u8, template_ma
/// Find all .pug files in a directory recursively
fn findPugFiles(allocator: mem.Allocator, dir_path: []const u8) ![][]const u8 {
var results: std.ArrayListUnmanaged([]const u8) = .{};
var results: std.ArrayList([]const u8) = .{};
errdefer {
for (results.items) |item| allocator.free(item);
results.deinit(allocator);
@@ -309,7 +309,7 @@ fn findPugFiles(allocator: mem.Allocator, dir_path: []const u8) ![][]const u8 {
return results.toOwnedSlice(allocator);
}
fn findPugFilesRecursive(allocator: mem.Allocator, dir_path: []const u8, results: *std.ArrayListUnmanaged([]const u8)) !void {
fn findPugFilesRecursive(allocator: mem.Allocator, dir_path: []const u8, results: *std.ArrayList([]const u8)) !void {
var dir = try fs.cwd().openDir(dir_path, .{ .iterate = true });
defer dir.close();
@@ -365,7 +365,7 @@ fn makeTemplateName(allocator: mem.Allocator, path: []const u8) ![]const u8 {
path;
// Replace / and - with _
var result: std.ArrayListUnmanaged(u8) = .{};
var result: std.ArrayList(u8) = .{};
defer result.deinit(allocator);
for (without_ext) |c| {

View File

@@ -45,11 +45,11 @@ pub const TypeInfo = struct {
pub const Codegen = struct {
allocator: Allocator,
output: std.ArrayListUnmanaged(u8),
output: std.ArrayList(u8),
indent_level: usize,
terse: bool, // HTML5 mode vs XHTML
// Buffer for combining consecutive static strings
static_buffer: std.ArrayListUnmanaged(u8),
static_buffer: std.ArrayList(u8),
// Type hints from @TypeOf annotations
type_hints: std.StringHashMap(TypeInfo),
// Current loop variable for field resolution inside each blocks
@@ -141,7 +141,7 @@ pub const Codegen = struct {
// Initialize buffer
try self.writeIndent();
try self.writeLine("var buf: std.ArrayListUnmanaged(u8) = .{};");
try self.writeLine("var buf: std.ArrayList(u8) = .{};");
try self.writeIndent();
try self.writeLine("defer buf.deinit(allocator);");
@@ -797,7 +797,7 @@ pub fn extractFieldNames(allocator: Allocator, ast: *Node) ![][]const u8 {
try extractFieldNamesRecursive(ast, &fields, &loop_vars);
// Convert to sorted slice and sanitize field names
var result: std.ArrayListUnmanaged([]const u8) = .{};
var result: std.ArrayList([]const u8) = .{};
errdefer {
for (result.items) |item| allocator.free(item);
result.deinit(allocator);

View File

@@ -311,7 +311,7 @@ pub const ViewEngine = struct {
// Normalize the path (resolve ".." and ".")
// We need to handle this manually since std.fs.path.resolve needs absolute paths
var components = std.ArrayListUnmanaged([]const u8){};
var components = std.ArrayList([]const u8){};
defer components.deinit(allocator);
var iter = std.mem.splitScalar(u8, joined, '/');

View File

@@ -19,7 +19,7 @@ pub const WalkOptions = struct {
/// Include dependencies (traverse into FileReference.ast if present)
include_dependencies: bool = false,
/// Parent node stack (managed internally during walk)
parents: std.ArrayListUnmanaged(*Node) = .{},
parents: std.ArrayList(*Node) = .{},
pub fn deinit(self: *WalkOptions, allocator: Allocator) void {
self.parents.deinit(allocator);
@@ -359,7 +359,7 @@ fn visitChildren(
/// Walk a list of nodes and merge results (handling array replacements)
fn walkAndMergeNodes(
allocator: Allocator,
nodes: *std.ArrayListUnmanaged(*Node),
nodes: *std.ArrayList(*Node),
before: ?BeforeCallback,
after: ?AfterCallback,
options: *WalkOptions,
@@ -484,9 +484,9 @@ pub fn collectNodes(
allocator: Allocator,
ast: *Node,
node_type: NodeType,
) WalkError!std.ArrayListUnmanaged(*Node) {
) WalkError!std.ArrayList(*Node) {
const Collector = struct {
collected: std.ArrayListUnmanaged(*Node) = .{},
collected: std.ArrayList(*Node) = .{},
alloc: Allocator,
target_type: NodeType,