aboutsummaryrefslogtreecommitdiff
path: root/src/html/Element.zig
diff options
context:
space:
mode:
Diffstat (limited to 'src/html/Element.zig')
-rw-r--r--src/html/Element.zig104
1 files changed, 104 insertions, 0 deletions
diff --git a/src/html/Element.zig b/src/html/Element.zig
new file mode 100644
index 0000000..8ecf31e
--- /dev/null
+++ b/src/html/Element.zig
@@ -0,0 +1,104 @@
+const Self = @This();
+
+pub const Content = union(enum) {
+ elements: []const Self,
+ string: []const u8,
+ void: void,
+
+ pub fn content(string: []const u8) @This() {
+ return .{ .string = string };
+ }
+
+ pub fn children(elements: []const Self) @This() {
+ return .{ .elements = elements };
+ }
+};
+
+pub const Attribute = struct {
+ name: []const u8,
+ value: []const u8,
+};
+
+tag: []const u8,
+attributes: []const Attribute,
+content: Content,
+
+fn attributesFrom(attributes: anytype) []const Attribute {
+ const T = @TypeOf(attributes);
+ const info = @typeInfo(T);
+
+ if (info != .@"struct") {
+ @compileError("struct needed");
+ }
+
+ const fields = info.@"struct".fields;
+
+ var attrs: []const Attribute = &.{};
+
+ for (fields) |field| {
+ const name = field.name;
+ const value = @field(attributes, name);
+
+ const next_attr: []const Attribute = &.{ .{ .name = name, .value = value } };
+ attrs = attrs ++ next_attr;
+ }
+
+ return attrs;
+}
+
+pub fn native(name: @EnumLiteral(), attrs: anytype, content: Content) Self {
+ return .{
+ .tag = @tagName(name),
+ .attributes = attributesFrom(attrs),
+ .content = content,
+ };
+}
+
+pub fn transparent(content: Content) Self {
+ return .{
+ .tag = "",
+ .attributes = &.{},
+ .content = content,
+ };
+}
+
+pub fn toHtml(comptime self: Self) []const u8 {
+ var string: []const u8 = string: {
+ if (self.tag.len == 0) {
+ break :string "";
+ }
+
+ var string: []const u8 = "<" ++ self.tag;
+
+ inline for (self.attributes) |attr| {
+ string = string ++ " " ++ attr.name ++ "='" ++ attr.value ++ "'";
+ }
+
+ string = string ++ ">";
+
+ break :string string;
+ };
+
+
+ switch (self.content) {
+ .void => {},
+ .string => |s| {
+ string = string ++ s ++ "</" ++ self.tag ++ ">";
+ },
+ .elements => |els| {
+ for (els) |el| {
+ string = string ++ el.toHtml();
+ }
+
+ string = string ++ "</" ++ self.tag ++ ">";
+ }
+ }
+
+ string = string ++ if (self.tag.len == 0) "" else "</" ++ self.tag ++ ">";
+
+ return string;
+}
+
+pub fn toDocument(comptime self: Self) []const u8 {
+ return "<!DOCTYPE html>" ++ self.toHtml();
+}