update: lorem
This commit is contained in:
parent
14e307f3dc
commit
24ecea0244
4 changed files with 853 additions and 201 deletions
338
src/lorem.zig
Normal file
338
src/lorem.zig
Normal file
|
|
@ -0,0 +1,338 @@
|
||||||
|
const std = @import("std");
|
||||||
|
const rand = std.crypto.random;
|
||||||
|
|
||||||
|
pub const LOREM_COMMON_P =
|
||||||
|
\\Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod
|
||||||
|
\\tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim
|
||||||
|
\\veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea
|
||||||
|
\\commodo consequat. Duis aute irure dolor in reprehenderit in voluptate
|
||||||
|
\\velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint
|
||||||
|
\\occaecat cupidatat non proident, sunt in culpa qui officia deserunt
|
||||||
|
\\mollit anim id est laborum.
|
||||||
|
;
|
||||||
|
|
||||||
|
pub const LOREM_WORDS = [182][]const u8{
|
||||||
|
"exercitationem",
|
||||||
|
"perferendis",
|
||||||
|
"perspiciatis",
|
||||||
|
"laborum",
|
||||||
|
"eveniet",
|
||||||
|
"sunt",
|
||||||
|
"iure",
|
||||||
|
"nam",
|
||||||
|
"nobis",
|
||||||
|
"eum",
|
||||||
|
"cum",
|
||||||
|
"officiis",
|
||||||
|
"excepturi",
|
||||||
|
"odio",
|
||||||
|
"consectetur",
|
||||||
|
"quasi",
|
||||||
|
"aut",
|
||||||
|
"quisquam",
|
||||||
|
"vel",
|
||||||
|
"eligendi",
|
||||||
|
"itaque",
|
||||||
|
"non",
|
||||||
|
"odit",
|
||||||
|
"tempore",
|
||||||
|
"quaerat",
|
||||||
|
"dignissimos",
|
||||||
|
"facilis",
|
||||||
|
"neque",
|
||||||
|
"nihil",
|
||||||
|
"expedita",
|
||||||
|
"vitae",
|
||||||
|
"vero",
|
||||||
|
"ipsum",
|
||||||
|
"nisi",
|
||||||
|
"animi",
|
||||||
|
"cumque",
|
||||||
|
"pariatur",
|
||||||
|
"velit",
|
||||||
|
"modi",
|
||||||
|
"natus",
|
||||||
|
"iusto",
|
||||||
|
"eaque",
|
||||||
|
"sequi",
|
||||||
|
"illo",
|
||||||
|
"sed",
|
||||||
|
"ex",
|
||||||
|
"et",
|
||||||
|
"voluptatibus",
|
||||||
|
"tempora",
|
||||||
|
"veritatis",
|
||||||
|
"ratione",
|
||||||
|
"assumenda",
|
||||||
|
"incidunt",
|
||||||
|
"nostrum",
|
||||||
|
"placeat",
|
||||||
|
"aliquid",
|
||||||
|
"fuga",
|
||||||
|
"provident",
|
||||||
|
"praesentium",
|
||||||
|
"rem",
|
||||||
|
"necessitatibus",
|
||||||
|
"suscipit",
|
||||||
|
"adipisci",
|
||||||
|
"quidem",
|
||||||
|
"possimus",
|
||||||
|
"voluptas",
|
||||||
|
"debitis",
|
||||||
|
"sint",
|
||||||
|
"accusantium",
|
||||||
|
"unde",
|
||||||
|
"sapiente",
|
||||||
|
"voluptate",
|
||||||
|
"qui",
|
||||||
|
"aspernatur",
|
||||||
|
"laudantium",
|
||||||
|
"soluta",
|
||||||
|
"amet",
|
||||||
|
"quo",
|
||||||
|
"aliquam",
|
||||||
|
"saepe",
|
||||||
|
"culpa",
|
||||||
|
"libero",
|
||||||
|
"ipsa",
|
||||||
|
"dicta",
|
||||||
|
"reiciendis",
|
||||||
|
"nesciunt",
|
||||||
|
"doloribus",
|
||||||
|
"autem",
|
||||||
|
"impedit",
|
||||||
|
"minima",
|
||||||
|
"maiores",
|
||||||
|
"repudiandae",
|
||||||
|
"ipsam",
|
||||||
|
"obcaecati",
|
||||||
|
"ullam",
|
||||||
|
"enim",
|
||||||
|
"totam",
|
||||||
|
"delectus",
|
||||||
|
"ducimus",
|
||||||
|
"quis",
|
||||||
|
"voluptates",
|
||||||
|
"dolores",
|
||||||
|
"molestiae",
|
||||||
|
"harum",
|
||||||
|
"dolorem",
|
||||||
|
"quia",
|
||||||
|
"voluptatem",
|
||||||
|
"molestias",
|
||||||
|
"magni",
|
||||||
|
"distinctio",
|
||||||
|
"omnis",
|
||||||
|
"illum",
|
||||||
|
"dolorum",
|
||||||
|
"voluptatum",
|
||||||
|
"ea",
|
||||||
|
"quas",
|
||||||
|
"quam",
|
||||||
|
"corporis",
|
||||||
|
"quae",
|
||||||
|
"blanditiis",
|
||||||
|
"atque",
|
||||||
|
"deserunt",
|
||||||
|
"laboriosam",
|
||||||
|
"earum",
|
||||||
|
"consequuntur",
|
||||||
|
"hic",
|
||||||
|
"cupiditate",
|
||||||
|
"quibusdam",
|
||||||
|
"accusamus",
|
||||||
|
"ut",
|
||||||
|
"rerum",
|
||||||
|
"error",
|
||||||
|
"minus",
|
||||||
|
"eius",
|
||||||
|
"ab",
|
||||||
|
"ad",
|
||||||
|
"nemo",
|
||||||
|
"fugit",
|
||||||
|
"officia",
|
||||||
|
"at",
|
||||||
|
"in",
|
||||||
|
"id",
|
||||||
|
"quos",
|
||||||
|
"reprehenderit",
|
||||||
|
"numquam",
|
||||||
|
"iste",
|
||||||
|
"fugiat",
|
||||||
|
"sit",
|
||||||
|
"inventore",
|
||||||
|
"beatae",
|
||||||
|
"repellendus",
|
||||||
|
"magnam",
|
||||||
|
"recusandae",
|
||||||
|
"quod",
|
||||||
|
"explicabo",
|
||||||
|
"doloremque",
|
||||||
|
"aperiam",
|
||||||
|
"consequatur",
|
||||||
|
"asperiores",
|
||||||
|
"commodi",
|
||||||
|
"optio",
|
||||||
|
"dolor",
|
||||||
|
"labore",
|
||||||
|
"temporibus",
|
||||||
|
"repellat",
|
||||||
|
"veniam",
|
||||||
|
"architecto",
|
||||||
|
"est",
|
||||||
|
"esse",
|
||||||
|
"mollitia",
|
||||||
|
"nulla",
|
||||||
|
"a",
|
||||||
|
"similique",
|
||||||
|
"eos",
|
||||||
|
"alias",
|
||||||
|
"dolore",
|
||||||
|
"tenetur",
|
||||||
|
"deleniti",
|
||||||
|
"porro",
|
||||||
|
"facere",
|
||||||
|
"maxime",
|
||||||
|
"corrupti",
|
||||||
|
};
|
||||||
|
|
||||||
|
pub const LOREM_COMMON_WORDS = [19][]const u8{
|
||||||
|
"lorem",
|
||||||
|
"ipsum",
|
||||||
|
"dolor",
|
||||||
|
"sit",
|
||||||
|
"amet",
|
||||||
|
"consectetur",
|
||||||
|
"adipisicing",
|
||||||
|
"elit",
|
||||||
|
"sed",
|
||||||
|
"do",
|
||||||
|
"eiusmod",
|
||||||
|
"tempor",
|
||||||
|
"incididunt",
|
||||||
|
"ut",
|
||||||
|
"labore",
|
||||||
|
"et",
|
||||||
|
"dolore",
|
||||||
|
"magna",
|
||||||
|
"aliqua",
|
||||||
|
};
|
||||||
|
|
||||||
|
pub fn sentence(allocator: std.mem.Allocator) ![]const u8 {
|
||||||
|
const num_sections = rand.intRangeAtMost(u32, 1, 4);
|
||||||
|
|
||||||
|
var parts = std.ArrayList([]u8){};
|
||||||
|
defer {
|
||||||
|
for (parts.items) |p| allocator.free(p);
|
||||||
|
parts.deinit(allocator);
|
||||||
|
}
|
||||||
|
|
||||||
|
var i: u32 = 0;
|
||||||
|
while (i < num_sections) : (i += 1) {
|
||||||
|
const num_words = rand.intRangeAtMost(u32, 3, 12);
|
||||||
|
|
||||||
|
var wds = std.ArrayList([]const u8){};
|
||||||
|
defer wds.deinit(allocator);
|
||||||
|
try wds.ensureTotalCapacity(allocator, num_words);
|
||||||
|
|
||||||
|
var j: u32 = 0;
|
||||||
|
while (j < num_words) : (j += 1) {
|
||||||
|
const idx = rand.intRangeAtMost(usize, 0, LOREM_WORDS.len - 1);
|
||||||
|
try wds.append(allocator, LOREM_WORDS[idx]);
|
||||||
|
}
|
||||||
|
|
||||||
|
const section = try std.mem.join(allocator, " ", wds.items);
|
||||||
|
try parts.append(allocator, section);
|
||||||
|
}
|
||||||
|
|
||||||
|
const text = try std.mem.join(allocator, ", ", parts.items);
|
||||||
|
defer allocator.free(text);
|
||||||
|
|
||||||
|
var result = try allocator.alloc(u8, text.len + 1);
|
||||||
|
if (text.len > 0) {
|
||||||
|
result[0] = std.ascii.toUpper(text[0]);
|
||||||
|
@memcpy(result[1..text.len], text[1..]);
|
||||||
|
}
|
||||||
|
result[text.len] = if (rand.boolean()) '.' else '?';
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn paragraph(allocator: std.mem.Allocator) ![]const u8 {
|
||||||
|
const num_sentences = rand.intRangeAtMost(u32, 1, 4);
|
||||||
|
var sentences = std.ArrayList([]const u8){};
|
||||||
|
defer sentences.deinit(allocator);
|
||||||
|
|
||||||
|
for (0..num_sentences) |_| {
|
||||||
|
try sentences.append(allocator, try sentence(allocator));
|
||||||
|
}
|
||||||
|
|
||||||
|
return try std.mem.join(allocator, ". ", sentences.items);
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn paragraphs(allocator: std.mem.Allocator, count: u32, random: bool) ![]const u8 {
|
||||||
|
var pa = std.ArrayList([]const u8){};
|
||||||
|
defer pa.deinit(allocator);
|
||||||
|
|
||||||
|
if (count == 0) return "";
|
||||||
|
|
||||||
|
if (random == true) {
|
||||||
|
for (0..count) |_| {
|
||||||
|
const pg = try paragraph(allocator);
|
||||||
|
if (pg.len > 0) {
|
||||||
|
try pa.append(allocator, try std.fmt.allocPrint(allocator, "<p>{s}</p>", .{pg}));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return try std.mem.join(allocator, "\n", pa.items);
|
||||||
|
}
|
||||||
|
|
||||||
|
const first = try std.fmt.allocPrint(allocator, "<p>{s}</p>", .{LOREM_COMMON_P});
|
||||||
|
if (count == 1) {
|
||||||
|
return first;
|
||||||
|
}
|
||||||
|
|
||||||
|
const ncount: u32 = count - 1;
|
||||||
|
try pa.append(allocator, first);
|
||||||
|
|
||||||
|
for (0..ncount) |_| {
|
||||||
|
const pg = try paragraph(allocator);
|
||||||
|
if (pg.len > 0) {
|
||||||
|
try pa.append(allocator, try std.fmt.allocPrint(allocator, "<p>{s}</p>", .{pg}));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return try std.mem.join(allocator, "\n", pa.items);
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn words(allocator: std.mem.Allocator, count: u32, random: bool) ![]const u8 {
|
||||||
|
var wd = std.ArrayList([]const u8){};
|
||||||
|
defer wd.deinit(allocator);
|
||||||
|
|
||||||
|
if (random == true) {
|
||||||
|
for (0..count) |_| {
|
||||||
|
const idx = rand.intRangeAtMost(usize, 0, LOREM_COMMON_WORDS.len - 1);
|
||||||
|
try wd.append(allocator, LOREM_COMMON_WORDS[idx]);
|
||||||
|
}
|
||||||
|
return try std.mem.join(allocator, " ", wd.items);
|
||||||
|
}
|
||||||
|
|
||||||
|
var inc: u32 = 0;
|
||||||
|
|
||||||
|
for (LOREM_COMMON_WORDS) |word| {
|
||||||
|
try wd.append(allocator, word);
|
||||||
|
inc += 1;
|
||||||
|
if (inc >= count or inc >= 20) break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (count >= 20) {
|
||||||
|
const ncount = count - inc;
|
||||||
|
|
||||||
|
for (0..ncount) |_| {
|
||||||
|
const idx = rand.intRangeAtMost(usize, 0, LOREM_COMMON_WORDS.len - 1);
|
||||||
|
try wd.append(allocator, LOREM_COMMON_WORDS[idx]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return try std.mem.join(allocator, " ", wd.items);
|
||||||
|
}
|
||||||
|
|
@ -202,6 +202,7 @@ pub const FilterBlockNode = struct {
|
||||||
|
|
||||||
pub const FirstOfNode = struct {
|
pub const FirstOfNode = struct {
|
||||||
values: []const []const u8,
|
values: []const []const u8,
|
||||||
|
fallback: []const u8,
|
||||||
};
|
};
|
||||||
|
|
||||||
pub const ForNode = struct {
|
pub const ForNode = struct {
|
||||||
|
|
@ -232,7 +233,7 @@ pub const LoadNode = struct {
|
||||||
pub const LoremNode = struct {
|
pub const LoremNode = struct {
|
||||||
count: ?[]const u8 = null, // "3" ou null
|
count: ?[]const u8 = null, // "3" ou null
|
||||||
method: ?[]const u8 = null, // "p" ou "w" ou null
|
method: ?[]const u8 = null, // "p" ou "w" ou null
|
||||||
format: ?[]const u8 = null, // "html" ou null
|
random: bool = false,
|
||||||
};
|
};
|
||||||
|
|
||||||
pub const NowNode = struct {
|
pub const NowNode = struct {
|
||||||
|
|
@ -450,10 +451,12 @@ pub const Node = struct {
|
||||||
values_copy[i] = try allocator.dupe(u8, f);
|
values_copy[i] = try allocator.dupe(u8, f);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const fallback_copy = try allocator.dupe(u8, self.tag.?.body.firstof.fallback);
|
||||||
|
|
||||||
return Node{ .type = .tag, .tag = .{
|
return Node{ .type = .tag, .tag = .{
|
||||||
.kind = .firstof,
|
.kind = .firstof,
|
||||||
.args = try allocator.dupe(u8, self.tag.?.args),
|
.args = try allocator.dupe(u8, self.tag.?.args),
|
||||||
.body = .{ .firstof = .{ .values = values_copy } },
|
.body = .{ .firstof = .{ .values = values_copy, .fallback = fallback_copy } },
|
||||||
.raw = try allocator.dupe(u8, self.tag.?.raw),
|
.raw = try allocator.dupe(u8, self.tag.?.raw),
|
||||||
} };
|
} };
|
||||||
},
|
},
|
||||||
|
|
@ -776,7 +779,7 @@ pub const Node = struct {
|
||||||
.lorem = .{
|
.lorem = .{
|
||||||
.count = if (self.tag.?.body.lorem.count) |c| try allocator.dupe(u8, c) else null,
|
.count = if (self.tag.?.body.lorem.count) |c| try allocator.dupe(u8, c) else null,
|
||||||
.method = if (self.tag.?.body.lorem.method) |m| try allocator.dupe(u8, m) else null,
|
.method = if (self.tag.?.body.lorem.method) |m| try allocator.dupe(u8, m) else null,
|
||||||
.format = if (self.tag.?.body.lorem.format) |f| try allocator.dupe(u8, f) else null,
|
.random = self.tag.?.body.lorem.random,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
|
@ -1375,7 +1378,7 @@ pub const Parser = struct {
|
||||||
if (tag_node.tag.?.kind == .comment) {
|
if (tag_node.tag.?.kind == .comment) {
|
||||||
try self.parseComment();
|
try self.parseComment();
|
||||||
continue;
|
continue;
|
||||||
}else {
|
} else {
|
||||||
if (try self.parseTagContent(allocator, tag_node)) |tn| {
|
if (try self.parseTagContent(allocator, tag_node)) |tn| {
|
||||||
tag.tag.?.body = tn;
|
tag.tag.?.body = tn;
|
||||||
try body.append(allocator, tag);
|
try body.append(allocator, tag);
|
||||||
|
|
@ -1843,6 +1846,7 @@ pub const Parser = struct {
|
||||||
var values = std.ArrayList([]const u8){};
|
var values = std.ArrayList([]const u8){};
|
||||||
defer values.deinit(allocator);
|
defer values.deinit(allocator);
|
||||||
var i: usize = 0;
|
var i: usize = 0;
|
||||||
|
var fallback: []const u8 = "";
|
||||||
while (i < args.len) {
|
while (i < args.len) {
|
||||||
while (i < args.len and std.ascii.isWhitespace(args[i])) : (i += 1) {}
|
while (i < args.len and std.ascii.isWhitespace(args[i])) : (i += 1) {}
|
||||||
|
|
||||||
|
|
@ -1870,12 +1874,17 @@ pub const Parser = struct {
|
||||||
}
|
}
|
||||||
|
|
||||||
const value = std.mem.trim(u8, args[start..i], " \t\r\n\"'");
|
const value = std.mem.trim(u8, args[start..i], " \t\r\n\"'");
|
||||||
try values.append(allocator, value);
|
if (in_quote) {
|
||||||
|
fallback = value;
|
||||||
|
} else {
|
||||||
|
try values.append(allocator, value);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return TagNodeBody{
|
return TagNodeBody{
|
||||||
.firstof = .{
|
.firstof = .{
|
||||||
.values = try values.toOwnedSlice(allocator),
|
.values = try values.toOwnedSlice(allocator),
|
||||||
|
.fallback = fallback,
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
|
|
@ -1936,7 +1945,7 @@ pub const Parser = struct {
|
||||||
const args = tag_node.tag.?.args;
|
const args = tag_node.tag.?.args;
|
||||||
var count: ?[]const u8 = null;
|
var count: ?[]const u8 = null;
|
||||||
var method: ?[]const u8 = null;
|
var method: ?[]const u8 = null;
|
||||||
var format: ?[]const u8 = null;
|
var random: bool = false;
|
||||||
|
|
||||||
var parts = std.mem.splitScalar(u8, args, ' ');
|
var parts = std.mem.splitScalar(u8, args, ' ');
|
||||||
while (parts.next()) |part| {
|
while (parts.next()) |part| {
|
||||||
|
|
@ -1950,8 +1959,8 @@ pub const Parser = struct {
|
||||||
|
|
||||||
if (std.mem.eql(u8, trimmed, "p") or std.mem.eql(u8, trimmed, "w")) {
|
if (std.mem.eql(u8, trimmed, "p") or std.mem.eql(u8, trimmed, "w")) {
|
||||||
method = trimmed;
|
method = trimmed;
|
||||||
} else if (std.mem.eql(u8, trimmed, "html") or std.mem.eql(u8, trimmed, "text")) {
|
} else if (std.mem.eql(u8, trimmed, "true")) {
|
||||||
format = trimmed;
|
random = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -1959,7 +1968,7 @@ pub const Parser = struct {
|
||||||
.lorem = .{
|
.lorem = .{
|
||||||
.count = count,
|
.count = count,
|
||||||
.method = method,
|
.method = method,
|
||||||
.format = format,
|
.random = random,
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
|
|
|
||||||
284
src/renderer.zig
284
src/renderer.zig
|
|
@ -11,6 +11,7 @@ const FilterError = @import("filters.zig").FilterError;
|
||||||
const parser = @import("parser.zig");
|
const parser = @import("parser.zig");
|
||||||
const TemplateCache = @import("cache.zig").TemplateCache;
|
const TemplateCache = @import("cache.zig").TemplateCache;
|
||||||
const time = @import("time.zig");
|
const time = @import("time.zig");
|
||||||
|
const lorem = @import("lorem.zig");
|
||||||
|
|
||||||
pub const RenderError = error{
|
pub const RenderError = error{
|
||||||
InvalidCharacter,
|
InvalidCharacter,
|
||||||
|
|
@ -309,181 +310,91 @@ pub const Renderer = struct {
|
||||||
|
|
||||||
try writer.writeAll(std.fmt.allocPrint(alloc, "{d}", .{ratio}) catch "0");
|
try writer.writeAll(std.fmt.allocPrint(alloc, "{d}", .{ratio}) catch "0");
|
||||||
},
|
},
|
||||||
.now =>{
|
.now => {
|
||||||
var format: []const u8 = node.tag.?.body.now.format;
|
var format: []const u8 = node.tag.?.body.now.format;
|
||||||
if (format.len == 0) format = "Y-m-d H:i:s";
|
if (format.len == 0) format = "Y-m-d H:i:s";
|
||||||
const datetime = try time.Time.now().toStringAlloc(alloc, format);
|
const datetime = try time.Time.now().toStringAlloc(alloc, format);
|
||||||
try writer.writeAll(datetime);
|
try writer.writeAll(datetime);
|
||||||
},
|
},
|
||||||
|
.csrf_token => {
|
||||||
|
const token = self.context.get("csrf_token");
|
||||||
|
if (token == null) return;
|
||||||
|
try writer.writeAll(std.fmt.allocPrint(alloc, "<input type=\"hidden\" name=\"csrfmiddlewaretoken\" value=\"{s}\">", .{token.?.string}) catch "");
|
||||||
|
},
|
||||||
|
.firstof => {
|
||||||
|
const values = node.tag.?.body.firstof.values;
|
||||||
|
for (values) |value| {
|
||||||
|
if (self.context.get(value)) |v| {
|
||||||
|
if (!isTruthy(v)) continue;
|
||||||
|
|
||||||
|
var buf = ArrayListUnmanaged(u8){};
|
||||||
|
defer buf.deinit(alloc);
|
||||||
|
|
||||||
|
try self.valueToString(alloc, &buf, v);
|
||||||
|
|
||||||
|
try writer.writeAll(buf.items);
|
||||||
|
return;
|
||||||
|
} else {
|
||||||
|
const check_value = self.resolveStringVariable(value).?;
|
||||||
|
if (!isTruthy(check_value)) continue;
|
||||||
|
|
||||||
|
var buf = ArrayListUnmanaged(u8){};
|
||||||
|
defer buf.deinit(alloc);
|
||||||
|
|
||||||
|
try self.valueToString(alloc, &buf, Value{ .string = value });
|
||||||
|
try writer.writeAll(buf.items);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
try writer.writeAll(node.tag.?.body.firstof.fallback);
|
||||||
|
},
|
||||||
|
.lorem => {
|
||||||
|
const count = node.tag.?.body.lorem.count;
|
||||||
|
const method = node.tag.?.body.lorem.method;
|
||||||
|
const random = node.tag.?.body.lorem.random;
|
||||||
|
|
||||||
|
if (count == null and method == null) {
|
||||||
|
if (random == false) {
|
||||||
|
try writer.writeAll(lorem.LOREM_COMMON_P);
|
||||||
|
return;
|
||||||
|
}else {
|
||||||
|
try writer.writeAll(try lorem.sentence(alloc));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const ncount: u32 = std.fmt.parseInt(u32, count.?, 10) catch 1;
|
||||||
|
if (std.mem.eql(u8, method.?, "p")) {
|
||||||
|
const lorem_ = try lorem.paragraphs(alloc, ncount, random);
|
||||||
|
try writer.writeAll(lorem_);
|
||||||
|
return;
|
||||||
|
} else {
|
||||||
|
const lorem_ = try lorem.words(alloc, ncount, random);
|
||||||
|
try writer.writeAll(lorem_);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
},
|
||||||
else => {},
|
else => {},
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn renderNode_old(self: *const Renderer, alloc: Allocator, nodes: []parser.Node, node: parser.Node, writer: anytype, context: ?*Context, parent_block_nodes: ?[]parser.Node) RenderError!void {
|
fn resolveStringVariable(self: *const Renderer, value: []const u8) ?Value {
|
||||||
switch (node.type) {
|
_ = self;
|
||||||
.text => try writer.writeAll(node.text.?.content),
|
if (std.mem.eql(u8, value, "true")) return Value{ .bool = true };
|
||||||
.variable => {
|
if (std.mem.eql(u8, value, "false")) return Value{ .bool = false };
|
||||||
const var_name = node.variable.?.expr;
|
const is_int = std.fmt.parseInt(i64, value, 10) catch |err| switch (err) {
|
||||||
var value: Value = Value.null;
|
error.InvalidCharacter => null,
|
||||||
if (context != null) {
|
error.Overflow => null,
|
||||||
value = context.?.get(var_name) orelse Value.null;
|
};
|
||||||
} else {
|
if (is_int != null) return Value{ .int = is_int.? };
|
||||||
value = self.context.get(var_name) orelse Value.null;
|
|
||||||
}
|
|
||||||
|
|
||||||
var is_safe = false;
|
const is_float = std.fmt.parseFloat(f64, value) catch |err| switch (err) {
|
||||||
|
error.InvalidCharacter => null,
|
||||||
for (node.variable.?.filters) |f| {
|
};
|
||||||
const filter_fn = builtin_filters.get(f.name) orelse return error.UnknownFilter;
|
if (is_float != null) return Value{ .float = is_float.? };
|
||||||
|
return Value{ .string = value };
|
||||||
// const arg = if (f.arg) |a| Value{ .string = a } else null;
|
|
||||||
var arg: Value = Value.null;
|
|
||||||
if (f.arg) |a| {
|
|
||||||
arg = Value{ .string = a };
|
|
||||||
const result = try std.fmt.parseInt(i64, a, 10);
|
|
||||||
if (std.math.maxInt(i64) < result) return error.Overflow;
|
|
||||||
arg = Value{ .int = result };
|
|
||||||
}
|
|
||||||
value = try filter_fn(alloc, value, arg);
|
|
||||||
|
|
||||||
if (std.mem.eql(u8, f.name, "safe")) is_safe = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!is_safe) {
|
|
||||||
if (builtin_filters.get("escape")) |escape_fn| {
|
|
||||||
value = try escape_fn(alloc, value, null);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
var buf = ArrayListUnmanaged(u8){};
|
|
||||||
defer buf.deinit(alloc);
|
|
||||||
|
|
||||||
try self.valueToString(alloc, &buf, value);
|
|
||||||
try writer.writeAll(buf.items);
|
|
||||||
},
|
|
||||||
.if_block => {
|
|
||||||
const condition = try self.evaluateCondition(alloc, node.@"if".?.condition);
|
|
||||||
|
|
||||||
if (condition) {
|
|
||||||
for (node.@"if".?.true_body) |child| {
|
|
||||||
try self.renderNode(alloc, nodes, child, writer, null, null);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
for (node.@"if".?.false_body) |child| {
|
|
||||||
try self.renderNode(alloc, nodes, child, writer, null, null);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
.include => {
|
|
||||||
const included_template = try self.readTemplateFile(node.include.?.template_name);
|
|
||||||
defer alloc.free(included_template);
|
|
||||||
|
|
||||||
var included_parser = parser.Parser.init(included_template);
|
|
||||||
const included_nodes = try included_parser.parse(alloc);
|
|
||||||
defer {
|
|
||||||
for (included_nodes) |n| n.deinit(alloc);
|
|
||||||
alloc.free(included_nodes);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Renderiza o include no contexto atual (sem novo contexto)
|
|
||||||
for (included_nodes) |included_node| {
|
|
||||||
try self.renderNode(alloc, nodes, included_node, writer, context, null);
|
|
||||||
}
|
|
||||||
},
|
|
||||||
.for_block => {
|
|
||||||
const list_value = self.context.get(node.@"for".?.iterable) orelse Value.null;
|
|
||||||
const list = switch (list_value) {
|
|
||||||
.list => |l| l,
|
|
||||||
else => return,
|
|
||||||
};
|
|
||||||
|
|
||||||
for (list) |item| {
|
|
||||||
var ctx = Context.init(alloc);
|
|
||||||
defer ctx.deinit();
|
|
||||||
|
|
||||||
try ctx.set(node.@"for".?.loop_var, item);
|
|
||||||
|
|
||||||
for (node.@"for".?.body) |child| {
|
|
||||||
try self.renderNode(alloc, nodes, child, writer, &ctx, null);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (node.@"for".?.body.len == 0) {
|
|
||||||
for (node.@"for".?.empty_body) |child| {
|
|
||||||
try self.renderNode(alloc, nodes, child, writer, &ctx, null);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
.super => {
|
|
||||||
if (parent_block_nodes) |parent| {
|
|
||||||
for (parent) |child| {
|
|
||||||
try self.renderNode(alloc, nodes, child, writer, null, null);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
.block => {
|
|
||||||
for (node.block.?.body) |child| {
|
|
||||||
const parent_content = parent_block_nodes orelse node.block.?.body;
|
|
||||||
try self.renderNode(alloc, nodes, child, writer, null, parent_content);
|
|
||||||
}
|
|
||||||
},
|
|
||||||
.widthratio => {
|
|
||||||
var divisor: Value = Value{ .float = 1.0 };
|
|
||||||
var float_divisor: f64 = 1.0;
|
|
||||||
|
|
||||||
var value: Value = Value{ .float = 1.0 };
|
|
||||||
var float_value: f64 = 1.0;
|
|
||||||
|
|
||||||
var max_value: Value = Value{ .float = 1.0 };
|
|
||||||
var float_max_value: f64 = 1.0;
|
|
||||||
|
|
||||||
if (!std.mem.eql(u8, node.widthratio.?.value, "")) {
|
|
||||||
value = Value{ .string = node.widthratio.?.value };
|
|
||||||
if (self.context.get(node.widthratio.?.value)) |v| {
|
|
||||||
value = v;
|
|
||||||
}
|
|
||||||
float_value = switch (value) {
|
|
||||||
.int => @as(f64, @floatFromInt(value.int)),
|
|
||||||
.float => value.float,
|
|
||||||
.string => std.fmt.parseFloat(f64, value.string) catch 1.0,
|
|
||||||
else => 1.0,
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!std.mem.eql(u8, node.widthratio.?.max_value, "")) {
|
|
||||||
max_value = Value{ .string = node.widthratio.?.max_value };
|
|
||||||
if (self.context.get(node.widthratio.?.max_value)) |v| {
|
|
||||||
max_value = v;
|
|
||||||
}
|
|
||||||
float_max_value = switch (max_value) {
|
|
||||||
.int => @as(f64, @floatFromInt(max_value.int)),
|
|
||||||
.float => max_value.float,
|
|
||||||
.string => std.fmt.parseFloat(f64, max_value.string) catch 1.0,
|
|
||||||
else => 1.0,
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
if (node.widthratio.?.divisor) |div| {
|
|
||||||
divisor = Value{ .string = div };
|
|
||||||
if (self.context.get(div)) |d| {
|
|
||||||
divisor = d;
|
|
||||||
}
|
|
||||||
float_divisor = switch (divisor) {
|
|
||||||
.int => @as(f64, @floatFromInt(divisor.int)),
|
|
||||||
.float => divisor.float,
|
|
||||||
.string => std.fmt.parseFloat(f64, divisor.string) catch 0.0,
|
|
||||||
else => 1.0,
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
const ratio = (float_value / float_max_value) * float_divisor;
|
|
||||||
|
|
||||||
try writer.writeAll(std.fmt.allocPrint(alloc, "{d}", .{ratio}) catch "0");
|
|
||||||
},
|
|
||||||
else => {},
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn findChildBlock(self: *const Renderer, nodes: []parser.Node, name: []const u8) ?parser.BlockNode {
|
fn findChildBlock(self: *const Renderer, nodes: []parser.Node, name: []const u8) ?parser.BlockNode {
|
||||||
|
|
@ -496,35 +407,26 @@ pub const Renderer = struct {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
fn toValue(self: *Context, value: anytype) RenderError!Value {
|
fn escapeHtml(self: *const Renderer, value: Value) !Value {
|
||||||
const T = @TypeOf(value);
|
const s = switch (value) {
|
||||||
return switch (@typeInfo(T)) {
|
.string => |str| str,
|
||||||
.bool => Value{ .bool = value },
|
else => return value,
|
||||||
.int, .comptime_int => Value{ .int = @intCast(value) },
|
|
||||||
.float, .comptime_float => Value{ .float = @floatCast(value) },
|
|
||||||
.pointer => Value{ .string = try std.fmt.allocPrint(self.allocator(), "{s}", .{value}) },
|
|
||||||
.@"struct" => blk: {
|
|
||||||
var dict = std.StringHashMapUnmanaged(Value){};
|
|
||||||
inline for (std.meta.fields(T)) |field| {
|
|
||||||
const field_val = @field(value, field.name);
|
|
||||||
const converted = try self.toValue(field_val);
|
|
||||||
try dict.put(self.allocator(), field.name, converted);
|
|
||||||
}
|
|
||||||
break :blk Value{ .dict = dict };
|
|
||||||
},
|
|
||||||
.array => blk: {
|
|
||||||
var list = try self.allocator().alloc(Value, value.len);
|
|
||||||
for (value, 0..) |item, i| {
|
|
||||||
list[i] = try self.toValue(item);
|
|
||||||
}
|
|
||||||
break :blk Value{ .list = list };
|
|
||||||
},
|
|
||||||
.optional => if (value) |v| try self.toValue(v) else .null,
|
|
||||||
.null => .null,
|
|
||||||
// CASO ESPECIAL: o valor já é um Value (ex: lista de Value)
|
|
||||||
.@"union" => if (T == Value) value else @compileError("Unsupported union type: " ++ @typeName(T)),
|
|
||||||
else => @compileError("Unsupported type: " ++ @typeName(T)),
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
var result = std.ArrayList(u8){};
|
||||||
|
|
||||||
|
for (s) |c| {
|
||||||
|
switch (c) {
|
||||||
|
'&' => try result.appendSlice(self.allocator, "&"),
|
||||||
|
'<' => try result.appendSlice(self.allocator, "<"),
|
||||||
|
'>' => try result.appendSlice(self.allocator, ">"),
|
||||||
|
'"' => try result.appendSlice(self.allocator, """),
|
||||||
|
'\'' => try result.appendSlice(self.allocator, "'"),
|
||||||
|
else => try result.append(self.allocator, c),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return Value{ .string = try result.toOwnedSlice(self.allocator) };
|
||||||
}
|
}
|
||||||
|
|
||||||
fn valueToString(self: *const Renderer, alloc: Allocator, buf: *ArrayListUnmanaged(u8), value: Value) RenderError!void {
|
fn valueToString(self: *const Renderer, alloc: Allocator, buf: *ArrayListUnmanaged(u8), value: Value) RenderError!void {
|
||||||
|
|
|
||||||
|
|
@ -652,8 +652,25 @@ test "renderer - now" {
|
||||||
try ctx.set("idade", Value{ .int = 20 });
|
try ctx.set("idade", Value{ .int = 20 });
|
||||||
|
|
||||||
const template =
|
const template =
|
||||||
// \\{% now \"Y-m-d H:i:s\" %}
|
|
||||||
\\{% now %}
|
\\{% now %}
|
||||||
|
\\{% now \"Y-m-d H:i:s\" %}
|
||||||
|
\\{% now \"Y" %}
|
||||||
|
\\{% now \"m\" %}
|
||||||
|
\\{% now \"n\" %}
|
||||||
|
\\{% now \"d\" %}
|
||||||
|
\\{% now \"j\" %}
|
||||||
|
\\{% now \"F\" %}
|
||||||
|
\\{% now \"M\" %}
|
||||||
|
\\{% now \"l\" %}
|
||||||
|
\\{% now \"D\" %}
|
||||||
|
\\{% now \"H:i:s\" %}
|
||||||
|
\\{% now \"H\" %}
|
||||||
|
\\{% now \"G\" %}
|
||||||
|
\\{% now \"i\" %}
|
||||||
|
\\{% now \"s\" %}
|
||||||
|
\\{% now \"a\" %}
|
||||||
|
\\{% now \"A\" %}
|
||||||
|
\\{% now \"P\" %}
|
||||||
;
|
;
|
||||||
|
|
||||||
var buf = std.ArrayList(u8){};
|
var buf = std.ArrayList(u8){};
|
||||||
|
|
@ -665,3 +682,389 @@ test "renderer - now" {
|
||||||
|
|
||||||
// try testing.expect(std.mem.indexOf(u8, buf.items, "Maior") != null);
|
// try testing.expect(std.mem.indexOf(u8, buf.items, "Maior") != null);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
test "renderer - csrf_token in context" {
|
||||||
|
std.debug.print("____________________________________________________\n", .{});
|
||||||
|
std.debug.print("15 - csrf_token in context\n", .{});
|
||||||
|
|
||||||
|
const alloc = testing.allocator;
|
||||||
|
var ctx = Context.init(alloc);
|
||||||
|
defer ctx.deinit();
|
||||||
|
|
||||||
|
var cache = TemplateCache.init(alloc);
|
||||||
|
defer cache.deinit();
|
||||||
|
|
||||||
|
const renderer = Renderer.init(&ctx, &cache);
|
||||||
|
|
||||||
|
const token: []const u8 = "zh5fyUSICjXNsDTtJCjl9A3O2dDSHhYFlIngAEO6PXK9NX56Z1XLEy7doYuPcE0u";
|
||||||
|
|
||||||
|
try ctx.set("csrf_token", token);
|
||||||
|
const template =
|
||||||
|
\\{% csrf_token %}
|
||||||
|
;
|
||||||
|
|
||||||
|
const expected =
|
||||||
|
\\<input type="hidden" name="csrfmiddlewaretoken" value="zh5fyUSICjXNsDTtJCjl9A3O2dDSHhYFlIngAEO6PXK9NX56Z1XLEy7doYuPcE0u">
|
||||||
|
;
|
||||||
|
var buf = std.ArrayList(u8){};
|
||||||
|
defer buf.deinit(alloc);
|
||||||
|
|
||||||
|
try renderer.renderString(template, buf.writer(alloc));
|
||||||
|
|
||||||
|
std.debug.print("OUTPUT:\n\n{s}\n", .{buf.items});
|
||||||
|
|
||||||
|
try testing.expectEqualStrings(expected, buf.items);
|
||||||
|
}
|
||||||
|
|
||||||
|
test "renderer - csrf_token not in context" {
|
||||||
|
std.debug.print("____________________________________________________\n", .{});
|
||||||
|
std.debug.print("16 - csrf_token not in context\n", .{});
|
||||||
|
|
||||||
|
const alloc = testing.allocator;
|
||||||
|
var ctx = Context.init(alloc);
|
||||||
|
defer ctx.deinit();
|
||||||
|
|
||||||
|
var cache = TemplateCache.init(alloc);
|
||||||
|
defer cache.deinit();
|
||||||
|
|
||||||
|
const renderer = Renderer.init(&ctx, &cache);
|
||||||
|
|
||||||
|
const template =
|
||||||
|
\\{% csrf_token %}
|
||||||
|
;
|
||||||
|
|
||||||
|
const expected =
|
||||||
|
\\
|
||||||
|
;
|
||||||
|
var buf = std.ArrayList(u8){};
|
||||||
|
defer buf.deinit(alloc);
|
||||||
|
|
||||||
|
try renderer.renderString(template, buf.writer(alloc));
|
||||||
|
|
||||||
|
// std.debug.print("OUTPUT:\n\n{s}\n", .{buf.items});
|
||||||
|
|
||||||
|
try testing.expectEqualStrings(expected, buf.items);
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO: add parse filters to variables
|
||||||
|
test "renderer - firstof withtout fallback" {
|
||||||
|
std.debug.print("____________________________________________________\n", .{});
|
||||||
|
std.debug.print("17 - firstof without fallback\n", .{});
|
||||||
|
|
||||||
|
const alloc = testing.allocator;
|
||||||
|
var ctx = Context.init(alloc);
|
||||||
|
defer ctx.deinit();
|
||||||
|
|
||||||
|
var cache = TemplateCache.init(alloc);
|
||||||
|
defer cache.deinit();
|
||||||
|
|
||||||
|
const renderer = Renderer.init(&ctx, &cache);
|
||||||
|
|
||||||
|
try ctx.set("var1", "");
|
||||||
|
try ctx.set("var2", "baz");
|
||||||
|
|
||||||
|
const template =
|
||||||
|
\\{% firstof var1 var2 %}
|
||||||
|
;
|
||||||
|
|
||||||
|
const expected =
|
||||||
|
\\baz
|
||||||
|
;
|
||||||
|
var buf = std.ArrayList(u8){};
|
||||||
|
defer buf.deinit(alloc);
|
||||||
|
|
||||||
|
try renderer.renderString(template, buf.writer(alloc));
|
||||||
|
|
||||||
|
// std.debug.print("OUTPUT:\n\n{s}\n", .{buf.items});
|
||||||
|
|
||||||
|
try testing.expectEqualStrings(expected, buf.items);
|
||||||
|
}
|
||||||
|
|
||||||
|
test "renderer - firstof with fallback" {
|
||||||
|
std.debug.print("____________________________________________________\n", .{});
|
||||||
|
std.debug.print("18 - firstof with fallback\n", .{});
|
||||||
|
|
||||||
|
const alloc = testing.allocator;
|
||||||
|
var ctx = Context.init(alloc);
|
||||||
|
defer ctx.deinit();
|
||||||
|
|
||||||
|
var cache = TemplateCache.init(alloc);
|
||||||
|
defer cache.deinit();
|
||||||
|
|
||||||
|
const renderer = Renderer.init(&ctx, &cache);
|
||||||
|
|
||||||
|
try ctx.set("var1", "");
|
||||||
|
try ctx.set("var2", 0);
|
||||||
|
|
||||||
|
const template =
|
||||||
|
\\{% firstof var1 var2 "Oops no value!" %}
|
||||||
|
;
|
||||||
|
|
||||||
|
const expected =
|
||||||
|
\\Oops no value!
|
||||||
|
;
|
||||||
|
var buf = std.ArrayList(u8){};
|
||||||
|
defer buf.deinit(alloc);
|
||||||
|
|
||||||
|
try renderer.renderString(template, buf.writer(alloc));
|
||||||
|
|
||||||
|
// std.debug.print("OUTPUT:\n\n{s}\n", .{buf.items});
|
||||||
|
|
||||||
|
try testing.expectEqualStrings(expected, buf.items);
|
||||||
|
}
|
||||||
|
|
||||||
|
test "renderer - firstof without value in context" {
|
||||||
|
std.debug.print("____________________________________________________\n", .{});
|
||||||
|
std.debug.print("19 - firstof without value in context\n", .{});
|
||||||
|
|
||||||
|
const alloc = testing.allocator;
|
||||||
|
var ctx = Context.init(alloc);
|
||||||
|
defer ctx.deinit();
|
||||||
|
|
||||||
|
var cache = TemplateCache.init(alloc);
|
||||||
|
defer cache.deinit();
|
||||||
|
|
||||||
|
const renderer = Renderer.init(&ctx, &cache);
|
||||||
|
|
||||||
|
const template =
|
||||||
|
\\{% firstof 0 true "Oops no value!" %}
|
||||||
|
;
|
||||||
|
|
||||||
|
const expected =
|
||||||
|
\\true
|
||||||
|
;
|
||||||
|
var buf = std.ArrayList(u8){};
|
||||||
|
defer buf.deinit(alloc);
|
||||||
|
|
||||||
|
try renderer.renderString(template, buf.writer(alloc));
|
||||||
|
|
||||||
|
// std.debug.print("OUTPUT:\n\n{s}\n", .{buf.items});
|
||||||
|
|
||||||
|
try testing.expectEqualStrings(expected, buf.items);
|
||||||
|
}
|
||||||
|
|
||||||
|
test "renderer - firstof missing vars" {
|
||||||
|
std.debug.print("____________________________________________________\n", .{});
|
||||||
|
std.debug.print("20 - firstof missing vars\n", .{});
|
||||||
|
|
||||||
|
const alloc = testing.allocator;
|
||||||
|
var ctx = Context.init(alloc);
|
||||||
|
defer ctx.deinit();
|
||||||
|
|
||||||
|
var cache = TemplateCache.init(alloc);
|
||||||
|
defer cache.deinit();
|
||||||
|
|
||||||
|
const renderer = Renderer.init(&ctx, &cache);
|
||||||
|
|
||||||
|
const template =
|
||||||
|
\\{% firstof %}
|
||||||
|
;
|
||||||
|
|
||||||
|
const expected =
|
||||||
|
\\
|
||||||
|
;
|
||||||
|
var buf = std.ArrayList(u8){};
|
||||||
|
defer buf.deinit(alloc);
|
||||||
|
|
||||||
|
try renderer.renderString(template, buf.writer(alloc));
|
||||||
|
|
||||||
|
// std.debug.print("OUTPUT:\n\n{s}\n", .{buf.items});
|
||||||
|
|
||||||
|
try testing.expectEqualStrings(expected, buf.items);
|
||||||
|
}
|
||||||
|
|
||||||
|
test "renderer - firstof missing vars with fallback" {
|
||||||
|
std.debug.print("____________________________________________________\n", .{});
|
||||||
|
std.debug.print("21 - firstof missing vars with fallback\n", .{});
|
||||||
|
|
||||||
|
const alloc = testing.allocator;
|
||||||
|
var ctx = Context.init(alloc);
|
||||||
|
defer ctx.deinit();
|
||||||
|
|
||||||
|
var cache = TemplateCache.init(alloc);
|
||||||
|
defer cache.deinit();
|
||||||
|
|
||||||
|
const renderer = Renderer.init(&ctx, &cache);
|
||||||
|
|
||||||
|
const template =
|
||||||
|
\\{% firstof "nothing here" %}
|
||||||
|
;
|
||||||
|
|
||||||
|
const expected =
|
||||||
|
\\nothing here
|
||||||
|
;
|
||||||
|
var buf = std.ArrayList(u8){};
|
||||||
|
defer buf.deinit(alloc);
|
||||||
|
|
||||||
|
try renderer.renderString(template, buf.writer(alloc));
|
||||||
|
|
||||||
|
// std.debug.print("OUTPUT:\n\n{s}\n", .{buf.items});
|
||||||
|
|
||||||
|
try testing.expectEqualStrings(expected, buf.items);
|
||||||
|
}
|
||||||
|
|
||||||
|
test "renderer - lorem" {
|
||||||
|
std.debug.print("____________________________________________________\n", .{});
|
||||||
|
std.debug.print("22 - lorem\n", .{});
|
||||||
|
|
||||||
|
const alloc = testing.allocator;
|
||||||
|
var ctx = Context.init(alloc);
|
||||||
|
defer ctx.deinit();
|
||||||
|
|
||||||
|
var cache = TemplateCache.init(alloc);
|
||||||
|
defer cache.deinit();
|
||||||
|
|
||||||
|
const renderer = Renderer.init(&ctx, &cache);
|
||||||
|
|
||||||
|
const template =
|
||||||
|
\\{% lorem %}
|
||||||
|
;
|
||||||
|
|
||||||
|
var buf = std.ArrayList(u8){};
|
||||||
|
defer buf.deinit(alloc);
|
||||||
|
|
||||||
|
try renderer.renderString(template, buf.writer(alloc));
|
||||||
|
|
||||||
|
std.debug.print("OUTPUT:\n\n{s}\n", .{buf.items});
|
||||||
|
|
||||||
|
try testing.expect(std.mem.indexOf(u8, buf.items, "Lorem ipsum") != null);
|
||||||
|
}
|
||||||
|
|
||||||
|
test "renderer - lorem with count and method words" {
|
||||||
|
std.debug.print("____________________________________________________\n", .{});
|
||||||
|
std.debug.print("23 - lorem with count and method words\n", .{});
|
||||||
|
|
||||||
|
const alloc = testing.allocator;
|
||||||
|
var ctx = Context.init(alloc);
|
||||||
|
defer ctx.deinit();
|
||||||
|
|
||||||
|
var cache = TemplateCache.init(alloc);
|
||||||
|
defer cache.deinit();
|
||||||
|
|
||||||
|
const renderer = Renderer.init(&ctx, &cache);
|
||||||
|
|
||||||
|
const template =
|
||||||
|
\\{% lorem 3 w %}
|
||||||
|
;
|
||||||
|
|
||||||
|
var buf = std.ArrayList(u8){};
|
||||||
|
defer buf.deinit(alloc);
|
||||||
|
|
||||||
|
try renderer.renderString(template, buf.writer(alloc));
|
||||||
|
|
||||||
|
std.debug.print("OUTPUT:\n\n{s}\n", .{buf.items});
|
||||||
|
|
||||||
|
try testing.expectEqualStrings("lorem ipsum dolor", buf.items);
|
||||||
|
}
|
||||||
|
|
||||||
|
test "renderer - lorem with count and method paragraphs" {
|
||||||
|
std.debug.print("____________________________________________________\n", .{});
|
||||||
|
std.debug.print("24 - lorem with count and method paragraphs\n", .{});
|
||||||
|
|
||||||
|
const alloc = testing.allocator;
|
||||||
|
var ctx = Context.init(alloc);
|
||||||
|
defer ctx.deinit();
|
||||||
|
|
||||||
|
var cache = TemplateCache.init(alloc);
|
||||||
|
defer cache.deinit();
|
||||||
|
|
||||||
|
const renderer = Renderer.init(&ctx, &cache);
|
||||||
|
|
||||||
|
const template =
|
||||||
|
\\{% lorem 5 p %}
|
||||||
|
;
|
||||||
|
|
||||||
|
var buf = std.ArrayList(u8){};
|
||||||
|
defer buf.deinit(alloc);
|
||||||
|
|
||||||
|
try renderer.renderString(template, buf.writer(alloc));
|
||||||
|
|
||||||
|
std.debug.print("OUTPUT:\n\n{s}\n", .{buf.items});
|
||||||
|
|
||||||
|
const qty = std.mem.count(u8, buf.items, "<p>");
|
||||||
|
try testing.expect(std.mem.indexOf(u8, buf.items, "Lorem ipsum dolor") != null);
|
||||||
|
try testing.expect(qty == 5);
|
||||||
|
}
|
||||||
|
|
||||||
|
test "renderer - lorem only random" {
|
||||||
|
std.debug.print("____________________________________________________\n", .{});
|
||||||
|
std.debug.print("25 - lorem only random\n", .{});
|
||||||
|
|
||||||
|
const alloc = testing.allocator;
|
||||||
|
var ctx = Context.init(alloc);
|
||||||
|
defer ctx.deinit();
|
||||||
|
|
||||||
|
var cache = TemplateCache.init(alloc);
|
||||||
|
defer cache.deinit();
|
||||||
|
|
||||||
|
const renderer = Renderer.init(&ctx, &cache);
|
||||||
|
|
||||||
|
const template =
|
||||||
|
\\{% lorem true %}
|
||||||
|
;
|
||||||
|
|
||||||
|
var buf = std.ArrayList(u8){};
|
||||||
|
defer buf.deinit(alloc);
|
||||||
|
|
||||||
|
try renderer.renderString(template, buf.writer(alloc));
|
||||||
|
|
||||||
|
std.debug.print("OUTPUT:\n\n{s}\n", .{buf.items});
|
||||||
|
|
||||||
|
try testing.expect(buf.items.len > 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
test "renderer - lorem words random" {
|
||||||
|
std.debug.print("____________________________________________________\n", .{});
|
||||||
|
std.debug.print("26 - lorem words random\n", .{});
|
||||||
|
|
||||||
|
const alloc = testing.allocator;
|
||||||
|
var ctx = Context.init(alloc);
|
||||||
|
defer ctx.deinit();
|
||||||
|
|
||||||
|
var cache = TemplateCache.init(alloc);
|
||||||
|
defer cache.deinit();
|
||||||
|
|
||||||
|
const renderer = Renderer.init(&ctx, &cache);
|
||||||
|
|
||||||
|
const template =
|
||||||
|
\\{% lorem 6 w true %}
|
||||||
|
;
|
||||||
|
|
||||||
|
var buf = std.ArrayList(u8){};
|
||||||
|
defer buf.deinit(alloc);
|
||||||
|
|
||||||
|
try renderer.renderString(template, buf.writer(alloc));
|
||||||
|
|
||||||
|
std.debug.print("OUTPUT:\n\n{s}\n", .{buf.items});
|
||||||
|
|
||||||
|
const spaces = std.mem.count(u8, buf.items, " ");
|
||||||
|
try testing.expect(spaces == 5);
|
||||||
|
}
|
||||||
|
|
||||||
|
test "renderer - lorem paragraphs random" {
|
||||||
|
std.debug.print("____________________________________________________\n", .{});
|
||||||
|
std.debug.print("26 - lorem paragraphs random\n", .{});
|
||||||
|
|
||||||
|
const alloc = testing.allocator;
|
||||||
|
var ctx = Context.init(alloc);
|
||||||
|
defer ctx.deinit();
|
||||||
|
|
||||||
|
var cache = TemplateCache.init(alloc);
|
||||||
|
defer cache.deinit();
|
||||||
|
|
||||||
|
const renderer = Renderer.init(&ctx, &cache);
|
||||||
|
|
||||||
|
const template =
|
||||||
|
\\{% lorem 3 p true %}
|
||||||
|
;
|
||||||
|
|
||||||
|
var buf = std.ArrayList(u8){};
|
||||||
|
defer buf.deinit(alloc);
|
||||||
|
|
||||||
|
try renderer.renderString(template, buf.writer(alloc));
|
||||||
|
|
||||||
|
std.debug.print("OUTPUT:\n\n{s}\n", .{buf.items});
|
||||||
|
|
||||||
|
const spaces = std.mem.count(u8, buf.items, "<p>");
|
||||||
|
try testing.expect(spaces == 3);
|
||||||
|
}
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue