Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Empty file added src/errors/writer.zig
Empty file.
83 changes: 83 additions & 0 deletions src/interfaces/node.zig
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,29 @@ const std = @import("std");
const assert = @import("std").debug.assert;
const renderErr = @import("../errors/render.zig").RenderError;

pub fn Writer(comptime T: type, comptime initial: []const T, comptime new: []const T) type {
return struct {
const store: []const T = initial ++ new;

fn Write(comptime value: []const T) type {
return Writer(T, store, value);
}

fn write(comptime value: []const T) type {
return Writer(T, store, value);
}

pub fn Value() []const T {
return store;
}
};
}

test "writer" {
const writer = Writer(u8, "Hello", "World");
std.testing.expectEqualStrings(writer.Value(), "HelloWorld");
}

pub const NodeType = enum { element, text, childless, attribute, nodes };

pub const Node = struct {
Expand Down Expand Up @@ -33,6 +56,66 @@ pub const Node = struct {
value: ?[]const u8,
};

pub fn render2(self: *const Node, _mem: type) type {
switch (self.data) {
.element => |elem| {
var mem = _mem.write("<");
mem = mem.write(elem.name);
if (elem.children) |children| {
for (children) |*child| {
if (child.node_type == .attribute) {
mem = child.render2(mem);
}
}
}
mem = mem.write(">");
if (elem.children) |children| {
for (children) |*child| {
if (child.node_type != .attribute) {
mem = child.render2(mem);
}
}
}
mem = mem.write("</");
mem = mem.write(elem.name);
mem = mem.write(">");
return mem;
},
.text => |txt| {
return _mem.write(txt.content);
},
.childless => |childlessElem| {
var mem = _mem.write("<");
mem = mem.write(childlessElem.name);
if (childlessElem.children) |children| {
for (children) |*child| {
assert(child.node_type == .attribute);
mem = child.render2(mem);
}
}
return mem.write("/>");
},
.attribute => |attr| {
var mem = _mem.write(" ");
mem = mem.write(attr.name);
if (attr.value) |attrValue| {
mem = mem.write("=\"");
mem = mem.write(attrValue);
mem = mem.write("\"");
}
return mem;
},
.nodes => |nodes| {
var mem = _mem;
if (nodes.children) |children| {
for (children) |*child| {
mem = child.render2(mem);
}
}
return mem;
},
}
}
pub fn render(self: *const Node, mem: std.ArrayList(u8).Writer) renderErr!void {
switch (self.data) {
.element => |elem| {
Expand Down
78 changes: 64 additions & 14 deletions src/main.zig
Original file line number Diff line number Diff line change
Expand Up @@ -7,18 +7,23 @@ const sample = @import("sample.zig");
const server = @import("server.zig");

pub fn main() !void {
var gpa = std.heap.GeneralPurposeAllocator(.{}){};
const allocator = gpa.allocator();
defer {
const deinit_status = gpa.deinit();
if (deinit_status == .leak) std.testing.expect(false) catch @panic("Leak detected!");
}
var arr: std.ArrayList(u8) = .{}; //.init(allocator);
defer arr.deinit(allocator);
const writer = arr.writer(allocator);
try sample.run(writer);
const samplePage = arr.items;
try server.runServer(samplePage);
// var gpa = std.heap.GeneralPurposeAllocator(.{}){};
// const allocator = gpa.allocator();
// defer {
// const deinit_status = gpa.deinit();
// if (deinit_status == .leak) std.testing.expect(false) catch @panic("Leak detected!");
// }
// var arr: std.ArrayList(u8) = .{}; //.init(allocator);
// defer arr.deinit(allocator);
// const writer = arr.writer(allocator);
// try sample.run(writer);
// const samplePage = arr.items;
// comptime {
// = sample.run2();
// }
@setEvalBranchQuota(5000);
const samplePage = comptime sample.run2();
try server.runServer(@constCast(samplePage));
}

fn Page(n: []const Node) Node {
Expand All @@ -34,7 +39,7 @@ test "components" {

const html = Page(&.{
el.Head(&.{
el.Title(&.{el.Text("My Page")}),
el.Title("My Page"),
}),
el.Body(&.{el.Div(&.{el.Text("Hello world!")})}),
});
Expand All @@ -46,6 +51,31 @@ test "components" {
try std.testing.expectEqualStrings(res, "<html><head><title>My Page</title></head><body><div>Hello world!</div></body></html>");
}

fn Writer(comptime T: type, comptime initial: []const T, comptime new: []const T) type {
return struct {
const store: []const T = initial ++ new;

fn Write(comptime value: []const T) type {
return Writer(T, store, value);
}

fn Value() []const T {
return store;
}
// store: []const T = initial ++ new,

// const Self = @This();

// fn Write(self: *Self, comptime value: []const T) type {
// return Writer(T, self.store, value);
// }

// fn Value(self: *Self) []const T {
// return self.store;
// }
};
}

test "html5" {
const allocator = std.heap.page_allocator;
var arr: std.ArrayList(u8) = .{}; //.init(allocator);
Expand All @@ -57,7 +87,7 @@ test "html5" {
el.Head(&.{
el.Meta(&.{attr.Charset("UTF-8")}),
el.Meta(&.{ attr.Name("viewport"), attr.Content("width=device-width, initial-scale=1") }),
el.Title(&.{el.Text("Document")}),
el.Title("Document"),
}),
el.Body(&.{el.Div(&.{
attr.Class("my-class"),
Expand All @@ -72,3 +102,23 @@ test "html5" {

try std.testing.expectEqualStrings(res, "<html lang=\"en\"><head><meta charset=\"UTF-8\"/><meta name=\"viewport\" content=\"width=device-width, initial-scale=1\"/><title>Document</title></head><body><div class=\"my-class\" data-username=\"johndoes\">Hello world!</div></body></html>");
}

test "comptime allocation" {
const a: []const u8 = "Hello";
const b: []const u8 = " World";
var c: []const u8 = "";
c = comptime blk: {
break :blk a ++ b;
};

// c = c ++ "!!";

std.debug.print("{d}", .{c.len});

try std.testing.expectEqualStrings(c, "Hello World");

const writer = Writer(u8, "Hello", " World");

const e = writer.Write("!!").Write("==").Value();
try std.testing.expectEqualStrings(e, "Hello World!!==");
}
1 change: 1 addition & 0 deletions src/root.zig
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ pub const el = @import("./components/elements.zig");
pub const attr = @import("./components/atributes.zig");
pub const wrappers = @import("./components/wrapper.zig");
pub const Node = @import("./interfaces/node.zig").Node;
pub const Writer = @import("./interfaces/node.zig").Writer;

test {
std.testing.log_level = .warn;
Expand Down
Loading