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:
@@ -4,7 +4,7 @@ const helpers = @import("helpers.zig");
|
||||
pub const Data = struct {};
|
||||
|
||||
pub fn render(allocator: std.mem.Allocator, _: Data) ![]const u8 {
|
||||
var buf: std.ArrayListUnmanaged(u8) = .{};
|
||||
var buf: std.ArrayList(u8) = .{};
|
||||
defer buf.deinit(allocator);
|
||||
|
||||
try buf.appendSlice(allocator, "<div class=\"'friend'\"><h3>friend_name</h3><p>friend_email</p><p>friend_about</p><span class=\"'tag'\">tag_value</span></div>");
|
||||
|
||||
@@ -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, "&"),
|
||||
|
||||
@@ -4,7 +4,7 @@ const helpers = @import("helpers.zig");
|
||||
pub const Data = struct {};
|
||||
|
||||
pub fn render(allocator: std.mem.Allocator, _: Data) ![]const u8 {
|
||||
var buf: std.ArrayListUnmanaged(u8) = .{};
|
||||
var buf: std.ArrayList(u8) = .{};
|
||||
defer buf.deinit(allocator);
|
||||
|
||||
try buf.appendSlice(allocator, "<p>Active</p><p>Inactive</p>");
|
||||
|
||||
@@ -4,7 +4,7 @@ const helpers = @import("helpers.zig");
|
||||
pub const Data = struct {};
|
||||
|
||||
pub fn render(allocator: std.mem.Allocator, _: Data) ![]const u8 {
|
||||
var buf: std.ArrayListUnmanaged(u8) = .{};
|
||||
var buf: std.ArrayList(u8) = .{};
|
||||
defer buf.deinit(allocator);
|
||||
|
||||
try buf.appendSlice(allocator, "<li><a href=\"/project\">project_name</a>: project_description</li>");
|
||||
|
||||
@@ -4,7 +4,7 @@ const helpers = @import("helpers.zig");
|
||||
pub const Data = struct {};
|
||||
|
||||
pub fn render(allocator: std.mem.Allocator, _: Data) ![]const u8 {
|
||||
var buf: std.ArrayListUnmanaged(u8) = .{};
|
||||
var buf: std.ArrayList(u8) = .{};
|
||||
defer buf.deinit(allocator);
|
||||
|
||||
try buf.appendSlice(allocator, "<div><h3>result_title</h3><span>$result_price</span></div>");
|
||||
|
||||
@@ -4,7 +4,7 @@ const helpers = @import("helpers.zig");
|
||||
pub const Data = struct {};
|
||||
|
||||
pub fn render(allocator: std.mem.Allocator, _: Data) ![]const u8 {
|
||||
var buf: std.ArrayListUnmanaged(u8) = .{};
|
||||
var buf: std.ArrayList(u8) = .{};
|
||||
defer buf.deinit(allocator);
|
||||
|
||||
try buf.appendSlice(allocator, "<p>Hello World</p>");
|
||||
|
||||
@@ -4,7 +4,7 @@ const helpers = @import("helpers.zig");
|
||||
pub const Data = struct {};
|
||||
|
||||
pub fn render(allocator: std.mem.Allocator, _: Data) ![]const u8 {
|
||||
var buf: std.ArrayListUnmanaged(u8) = .{};
|
||||
var buf: std.ArrayList(u8) = .{};
|
||||
defer buf.deinit(allocator);
|
||||
|
||||
try buf.appendSlice(allocator, "<!DOCTYPE html><html><head><title>My Site</title></head><body><h1>Welcome</h1><p>This is a simple page</p></body></html>");
|
||||
|
||||
@@ -4,7 +4,7 @@ const helpers = @import("helpers.zig");
|
||||
pub const Data = struct {};
|
||||
|
||||
pub fn render(allocator: std.mem.Allocator, _: Data) ![]const u8 {
|
||||
var buf: std.ArrayListUnmanaged(u8) = .{};
|
||||
var buf: std.ArrayList(u8) = .{};
|
||||
defer buf.deinit(allocator);
|
||||
|
||||
try buf.appendSlice(allocator, "<h1>Header</h1><h2>Header2</h2><h3>Header3</h3><h4>Header4</h4><h5>Header5</h5><h6>Header6</h6><ul><li>item1</li><li>item2</li><li>item3</li></ul>");
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
.{
|
||||
.name = .pugz,
|
||||
.version = "0.3.7",
|
||||
.version = "0.3.8",
|
||||
.fingerprint = 0x822db0790e17621d, // Changing this has security and trust implications.
|
||||
.minimum_zig_version = "0.15.2",
|
||||
.dependencies = .{},
|
||||
|
||||
@@ -12,6 +12,10 @@ Pugz is a Pug-like HTML template engine written in Zig 0.15.2. It compiles Pug t
|
||||
- When the user specifies a new rule, update this CLAUDE.md file to include it.
|
||||
- Code comments are required but must be meaningful, not bloated. Focus on explaining "why" not "what". Avoid obvious comments like "// increment counter" - instead explain complex logic, non-obvious decisions, or tricky edge cases.
|
||||
- **All documentation files (.md) must be saved to the `docs/` directory.** Do not create .md files in the root directory or examples directories - always place them in `docs/`.
|
||||
- **Follow Zig standards for the version specified in `build.zig.zon`** (currently 0.15.2). This includes:
|
||||
- Use `std.ArrayList(T)` instead of the deprecated `std.ArrayListUnmanaged(T)` (renamed in Zig 0.15)
|
||||
- Pass allocator to method calls (`append`, `deinit`, etc.) as per the unmanaged pattern
|
||||
- Check Zig release notes for API changes when updating the minimum Zig version
|
||||
- **Publish command**: Only when user explicitly says "publish", do the following:
|
||||
1. Bump the fix version (patch version in build.zig.zon)
|
||||
2. Git commit with appropriate message
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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();
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
|
||||
|
||||
@@ -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) {
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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").?);
|
||||
}
|
||||
|
||||
@@ -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) {
|
||||
|
||||
@@ -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 ’ or &
|
||||
/// 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
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -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 ’
|
||||
/// 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);
|
||||
}
|
||||
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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, "&"),
|
||||
@@ -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),
|
||||
|
||||
@@ -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| {
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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, '/');
|
||||
|
||||
@@ -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,
|
||||
|
||||
|
||||
Reference in New Issue
Block a user