aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/eval/Element.zig52
-rw-r--r--src/eval/Image.zig10
-rw-r--r--src/eval/Root.zig10
-rw-r--r--src/eval/Title.zig24
-rw-r--r--src/eval/blocks.zig43
-rw-r--r--src/eval/html/Content.zig4
-rw-r--r--src/eval/html/Element.zig9
-rw-r--r--src/eval/html/Literal.zig4
-rw-r--r--src/eval/html/Root.zig4
-rw-r--r--src/eval/html/Void.zig4
-rw-r--r--src/eval/list.zig10
-rw-r--r--src/eval/math.zig11
-rw-r--r--src/eval/paragraph.zig10
13 files changed, 77 insertions, 118 deletions
diff --git a/src/eval/Element.zig b/src/eval/Element.zig
index 228e36c..9e8f70e 100644
--- a/src/eval/Element.zig
+++ b/src/eval/Element.zig
@@ -13,6 +13,38 @@ pub const Callout = blocks.Callout;
pub const Quote = blocks.Quote;
pub const Math = @import("math.zig");
+pub fn Wrapper(comptime V: type, comptime h: *const fn (*V, Allocator) HTML.Error!HTML) type {
+ comptime {
+ if (!@hasField(V, "node")) @compileError("missing field 'node' for " ++ @typeName(V));
+ const nd = @FieldType(V, "node");
+ if (nd != Node) @compileError("invalid node's type: " ++ @typeName(nd) ++ ", want " ++ @typeName(Node));
+ if (!std.meta.hasMethod(V, "element")) @compileError("missing declaration 'element' for " ++ @typeName(V));
+ }
+ return struct {
+ ptr: *V,
+
+ const Self = @This();
+
+ fn node(context: *anyopaque) *Node {
+ const self: *V = @ptrCast(@alignCast(context));
+ return &self.node;
+ }
+
+ fn html(context: *anyopaque, alloc: Allocator) HTML.Error!HTML {
+ const self: *V = @ptrCast(@alignCast(context));
+ return try h(self, alloc);
+ }
+
+ pub fn init(ptr: *V) Element {
+ return (Self{ .ptr = ptr }).element();
+ }
+
+ pub fn element(self: Self) Element {
+ return .{ .ptr = self.ptr, .vtable = .{ .node = Self.node, .html = Self.html } };
+ }
+ };
+}
+
pub const Node = struct {
ptr: *anyopaque,
vtable: struct { element: *const fn (*anyopaque) Element },
@@ -68,12 +100,7 @@ pub const Literal = struct {
}
pub fn element(self: *Self) Element {
- return .{ .ptr = self, .vtable = .{ .html = Self.html, .node = getNode } };
- }
-
- fn getNode(context: *anyopaque) *Node {
- const self: *Self = @ptrCast(@alignCast(context));
- return &self.node;
+ return Wrapper(Self, Self.html).init(self);
}
fn fromNode(context: *anyopaque) Element {
@@ -81,8 +108,7 @@ pub const Literal = struct {
return self.element();
}
- fn html(context: *anyopaque, alloc: Allocator) HTML.Error!HTML {
- const self: *Self = @ptrCast(@alignCast(context));
+ fn html(self: *Self, alloc: Allocator) HTML.Error!HTML {
return (try HTML.Literal.init(alloc, self.content)).element();
}
};
@@ -101,7 +127,7 @@ pub fn Simple(comptime tag: []const u8) type {
}
pub fn element(self: *Self) Element {
- return .{ .ptr = self, .vtable = .{ .html = Self.html, .node = getNode } };
+ return Wrapper(Self, Self.html).init(self);
}
pub fn toTag(self: *Self, alloc: Allocator, comptime target: []const u8) !*Simple(target) {
@@ -118,18 +144,12 @@ pub fn Simple(comptime tag: []const u8) type {
return el;
}
- fn getNode(context: *anyopaque) *Node {
- const self: *Self = @ptrCast(@alignCast(context));
- return &self.node;
- }
-
fn fromNode(context: *anyopaque) Element {
const self: *Self = @ptrCast(@alignCast(context));
return self.element();
}
- fn html(context: *anyopaque, alloc: Allocator) HTML.Error!HTML {
- const self: *Self = @ptrCast(@alignCast(context));
+ fn html(self: *Self, alloc: Allocator) HTML.Error!HTML {
var el = try HTML.Content.init(alloc, tag);
if (self.content) |it| el.content = try it.html(alloc);
return el.element();
diff --git a/src/eval/Image.zig b/src/eval/Image.zig
index 3e0132a..ef4f398 100644
--- a/src/eval/Image.zig
+++ b/src/eval/Image.zig
@@ -21,12 +21,7 @@ pub fn init(alloc: Allocator, src: []const u8) !*Self {
}
pub fn element(self: *Self) Element {
- return .{ .ptr = self, .vtable = .{ .html = html, .node = getNode } };
-}
-
-fn getNode(context: *anyopaque) *Node {
- const self: *Self = @ptrCast(@alignCast(context));
- return &self.node;
+ return Element.Wrapper(Self, html).init(self);
}
fn fromNode(context: *anyopaque) Element {
@@ -34,8 +29,7 @@ fn fromNode(context: *anyopaque) Element {
return self.element();
}
-fn html(context: *anyopaque, alloc: Allocator) HTML.Error!HTML {
- const self: *Self = @ptrCast(@alignCast(context));
+fn html(self: *Self, alloc: Allocator) HTML.Error!HTML {
var img = try HTML.Void.init(alloc, "img");
try img.setAttribute("src", self.src);
if (self.alt) |it| try img.setAttribute("alt", it);
diff --git a/src/eval/Root.zig b/src/eval/Root.zig
index 048dd3b..15c03e8 100644
--- a/src/eval/Root.zig
+++ b/src/eval/Root.zig
@@ -42,25 +42,19 @@ pub fn append(self: *Self, raw: anytype) void {
}
pub fn element(self: *Self) Element {
- return .{ .vtable = .{ .html = html, .node = getNode }, .ptr = self };
+ return Element.Wrapper(Self, html).init(self);
}
pub fn renderHTML(self: *Self, alloc: Allocator) HTML.Error![]const u8 {
return try self.element().renderHTML(alloc);
}
-fn getNode(context: *anyopaque) *Node {
- const self: *Self = @ptrCast(@alignCast(context));
- return &self.node;
-}
-
fn fromNode(context: *anyopaque) Element {
const self: *Self = @ptrCast(@alignCast(context));
return self.element();
}
-fn html(context: *anyopaque, alloc: Allocator) HTML.Error!HTML {
- const self: *Self = @ptrCast(@alignCast(context));
+fn html(self: *Self, alloc: Allocator) HTML.Error!HTML {
const el = try HTML.Root.init(alloc);
var v = self.content.first;
while (v) |it| : (v = it.next) try el.append(Node.from(it).element());
diff --git a/src/eval/Title.zig b/src/eval/Title.zig
index 1841ce7..1300832 100644
--- a/src/eval/Title.zig
+++ b/src/eval/Title.zig
@@ -1,11 +1,11 @@
const std = @import("std");
const Allocator = std.mem.Allocator;
-const HTML = Parent.HTML;
-const Parent = @import("Element.zig");
-const Node = Parent.Node;
+const HTML = Element.HTML;
+const Element = @import("Element.zig");
+const Node = Element.Node;
level: u3,
-content: Parent,
+content: Element,
node: Node = .{
.ptr = undefined,
.vtable = .{ .element = fromNode },
@@ -13,29 +13,23 @@ node: Node = .{
const Self = @This();
-pub fn init(alloc: Allocator, level: u3, content: Parent) !*Self {
+pub fn init(alloc: Allocator, level: u3, content: Element) !*Self {
const v = try alloc.create(Self);
v.* = .{ .level = level, .content = content };
v.node.ptr = v;
return v;
}
-pub fn element(self: *Self) Parent {
- return .{ .ptr = self, .vtable = .{ .html = html, .node = getNode } };
+pub fn element(self: *Self) Element {
+ return Element.Wrapper(Self, html).init(self);
}
-fn getNode(context: *anyopaque) *Node {
- const self: *Self = @ptrCast(@alignCast(context));
- return &self.node;
-}
-
-fn fromNode(context: *anyopaque) Parent {
+fn fromNode(context: *anyopaque) Element {
const self: *Self = @ptrCast(@alignCast(context));
return self.element();
}
-fn html(context: *anyopaque, alloc: Allocator) HTML.Error!HTML {
- const self: *Self = @ptrCast(@alignCast(context));
+fn html(self: *Self, alloc: Allocator) HTML.Error!HTML {
var el = try HTML.Content.init(alloc, switch (self.level) {
1 => "h1",
2 => "h2",
diff --git a/src/eval/blocks.zig b/src/eval/blocks.zig
index 9357799..03b0d00 100644
--- a/src/eval/blocks.zig
+++ b/src/eval/blocks.zig
@@ -22,15 +22,7 @@ pub const Code = struct {
}
pub fn element(self: *Self) Element {
- return .{ .ptr = self, .vtable = .{
- .html = html,
- .node = getNode,
- } };
- }
-
- fn getNode(context: *anyopaque) *Node {
- const self: *Self = @ptrCast(@alignCast(context));
- return &self.node;
+ return Element.Wrapper(Self, html).init(self);
}
fn fromNode(context: *anyopaque) Element {
@@ -38,8 +30,7 @@ pub const Code = struct {
return self.element();
}
- fn html(context: *anyopaque, alloc: Allocator) HTML.Error!HTML {
- const self: *Self = @ptrCast(@alignCast(context));
+ fn html(self: *Self, alloc: Allocator) HTML.Error!HTML {
var el = try HTML.Content.init(alloc, "pre");
if (self.attribute) |attr| try el.base.setAttribute("data-code", attr);
var code = try HTML.Content.init(alloc, "code");
@@ -69,12 +60,7 @@ pub const Figure = struct {
}
pub fn element(self: *Self) Element {
- return .{ .ptr = self, .vtable = .{ .html = html, .node = getNode } };
- }
-
- fn getNode(context: *anyopaque) *Node {
- const self: *Self = @ptrCast(@alignCast(context));
- return &self.node;
+ return Element.Wrapper(Self, html).init(self);
}
fn fromNode(context: *anyopaque) Element {
@@ -82,8 +68,7 @@ pub const Figure = struct {
return self.element();
}
- fn html(context: *anyopaque, parent: Allocator) HTML.Error!HTML {
- const self: *Self = @ptrCast(@alignCast(context));
+ fn html(self: *Self, parent: Allocator) HTML.Error!HTML {
var el = try HTML.Content.init(parent, "figure");
var root = try HTML.Root.init(parent);
const alloc = root.allocator();
@@ -116,12 +101,7 @@ pub const Callout = struct {
}
pub fn element(self: *Self) Element {
- return .{ .ptr = self, .vtable = .{ .html = html, .node = getNode } };
- }
-
- fn getNode(context: *anyopaque) *Node {
- const self: *Self = @ptrCast(@alignCast(context));
- return &self.node;
+ return Element.Wrapper(Self, html).init(self);
}
fn fromNode(context: *anyopaque) Element {
@@ -129,8 +109,7 @@ pub const Callout = struct {
return self.element();
}
- fn html(context: *anyopaque, alloc: Allocator) HTML.Error!HTML {
- const self: *Self = @ptrCast(@alignCast(context));
+ fn html(self: *Self, alloc: Allocator) HTML.Error!HTML {
var el = try HTML.Content.init(alloc, "div");
try el.base.appendClass("callout");
const kind = self.kind orelse "default";
@@ -162,12 +141,7 @@ pub const Quote = struct {
}
pub fn element(self: *Self) Element {
- return .{ .ptr = self, .vtable = .{ .html = html, .node = getNode } };
- }
-
- fn getNode(context: *anyopaque) *Node {
- const self: *Self = @ptrCast(@alignCast(context));
- return &self.node;
+ return Element.Wrapper(Self, html).init(self);
}
fn fromNode(context: *anyopaque) Element {
@@ -175,8 +149,7 @@ pub const Quote = struct {
return self.element();
}
- fn html(context: *anyopaque, alloc: Allocator) HTML.Error!HTML {
- const self: *Self = @ptrCast(@alignCast(context));
+ fn html(self: *Self, alloc: Allocator) HTML.Error!HTML {
const quote = try HTML.Content.init(alloc, "blockquote");
quote.content = try self.content.html(alloc);
return quote.element();
diff --git a/src/eval/html/Content.zig b/src/eval/html/Content.zig
index 96961da..7b9da3e 100644
--- a/src/eval/html/Content.zig
+++ b/src/eval/html/Content.zig
@@ -28,7 +28,7 @@ pub fn init(alloc: Allocator, tag: []const u8) Error!*Self {
}
pub fn element(self: *Self) Element {
- return (Element.Wrapper(Self){ .ptr = self }).element();
+ return Element.Wrapper(Self, render).init(self);
}
fn fromNode(context: *anyopaque) Element {
@@ -36,7 +36,7 @@ fn fromNode(context: *anyopaque) Element {
return self.element();
}
-pub fn render(self: *Self, alloc: Allocator) Error![]const u8 {
+fn render(self: *Self, alloc: Allocator) Error![]const u8 {
var base = self.base;
const b = try base.element().render(alloc);
defer alloc.free(b);
diff --git a/src/eval/html/Element.zig b/src/eval/html/Element.zig
index 52ee58d..dd24bea 100644
--- a/src/eval/html/Element.zig
+++ b/src/eval/html/Element.zig
@@ -11,13 +11,12 @@ pub const Root = @import("Root.zig");
pub const Error = html.Error || Allocator.Error;
-pub fn Wrapper(comptime V: type) type {
+pub fn Wrapper(comptime V: type, comptime r: *const fn (*V, Allocator) Error![]const u8) type {
comptime {
if (!@hasField(V, "node")) @compileError("missing field 'node' for " ++ @typeName(V));
const nd = @FieldType(V, "node");
if (nd != Node) @compileError("invalid node's type: " ++ @typeName(nd) ++ ", want " ++ @typeName(Node));
if (!std.meta.hasMethod(V, "element")) @compileError("missing declaration 'element' for " ++ @typeName(V));
- if (!std.meta.hasMethod(V, "render")) @compileError("missing declaration 'render' for " ++ @typeName(V));
}
return struct {
ptr: *V,
@@ -31,7 +30,11 @@ pub fn Wrapper(comptime V: type) type {
fn render(context: *anyopaque, alloc: Allocator) Error![]const u8 {
const self: *V = @ptrCast(@alignCast(context));
- return try self.render(alloc);
+ return try r(self, alloc);
+ }
+
+ pub fn init(ptr: *V) Element {
+ return (Self{ .ptr = ptr }).element();
}
pub fn element(self: Self) Element {
diff --git a/src/eval/html/Literal.zig b/src/eval/html/Literal.zig
index 9d6d91e..a5eb199 100644
--- a/src/eval/html/Literal.zig
+++ b/src/eval/html/Literal.zig
@@ -28,7 +28,7 @@ pub fn initNoEscape(alloc: Allocator, literal: []const u8) Error!*Element.Litera
}
pub fn element(self: *Self) Element {
- return (Element.Wrapper(Self){ .ptr = self }).element();
+ return Element.Wrapper(Self, render).init(self);
}
fn fromNode(context: *anyopaque) Element {
@@ -36,6 +36,6 @@ fn fromNode(context: *anyopaque) Element {
return self.element();
}
-pub fn render(self: *Self, alloc: Allocator) Error![]const u8 {
+fn render(self: *Self, alloc: Allocator) Error![]const u8 {
return try alloc.dupe(u8, self.literal);
}
diff --git a/src/eval/html/Root.zig b/src/eval/html/Root.zig
index 6c4c37a..af130d1 100644
--- a/src/eval/html/Root.zig
+++ b/src/eval/html/Root.zig
@@ -28,7 +28,7 @@ pub fn deinit(self: *Self) void {
}
pub fn element(self: *Self) Element {
- return (Element.Wrapper(Self){ .ptr = self }).element();
+ return Element.Wrapper(Self, render).init(self);
}
pub fn allocator(self: *Self) Allocator {
@@ -50,7 +50,7 @@ fn fromNode(context: *anyopaque) Element {
return self.element();
}
-pub fn render(self: *Self, alloc: Allocator) Error![]const u8 {
+fn render(self: *Self, alloc: Allocator) Error![]const u8 {
if (self.content.first == null) return "";
var acc = try std.ArrayList(u8).initCapacity(alloc, 8);
errdefer acc.deinit(alloc);
diff --git a/src/eval/html/Void.zig b/src/eval/html/Void.zig
index 431536c..17b369d 100644
--- a/src/eval/html/Void.zig
+++ b/src/eval/html/Void.zig
@@ -30,7 +30,7 @@ pub fn init(alloc: Allocator, tag: []const u8) Error!*Self {
}
pub fn element(self: *Self) Element {
- return (Element.Wrapper(Self){ .ptr = self }).element();
+ return Element.Wrapper(Self, render).init(self);
}
pub fn setAttribute(self: *Self, k: []const u8, v: []const u8) Error!void {
@@ -62,7 +62,7 @@ fn fromNode(context: *anyopaque) Element {
return self.element();
}
-pub fn render(self: *Self, alloc: Allocator) Error![]const u8 {
+fn render(self: *Self, alloc: Allocator) Error![]const u8 {
const attr = try renderAttribute(alloc, &self.attributes, &self.class_list);
defer if (attr) |it| alloc.free(it);
var acc = try List(u8).initCapacity(alloc, self.tag.len + 2);
diff --git a/src/eval/list.zig b/src/eval/list.zig
index 160bde2..0b1306a 100644
--- a/src/eval/list.zig
+++ b/src/eval/list.zig
@@ -24,12 +24,7 @@ fn List(comptime tag: []const u8) type {
}
pub fn element(self: *Self) Element {
- return .{ .ptr = self, .vtable = .{ .html = html, .node = getNode } };
- }
-
- fn getNode(context: *anyopaque) *Node {
- const self: *Self = @ptrCast(@alignCast(context));
- return &self.node;
+ return Element.Wrapper(Self, html).init(self);
}
fn fromNode(context: *anyopaque) Element {
@@ -37,8 +32,7 @@ fn List(comptime tag: []const u8) type {
return self.element();
}
- fn html(context: *anyopaque, alloc: Allocator) HTML.Error!HTML {
- const self: *Self = @ptrCast(@alignCast(context));
+ fn html(self: *Self, alloc: Allocator) HTML.Error!HTML {
var el = try HTML.Content.init(alloc, tag);
var root = try HTML.Root.init(alloc);
el.content = root.element();
diff --git a/src/eval/math.zig b/src/eval/math.zig
index 20d3fec..aeec997 100644
--- a/src/eval/math.zig
+++ b/src/eval/math.zig
@@ -54,12 +54,7 @@ fn Math(comptime template: []const u8) type {
}
pub fn element(self: *Self) Element {
- return .{ .ptr = self, .vtable = .{ .html = html, .node = getNode } };
- }
-
- fn getNode(context: *anyopaque) *Node {
- const self: *Self = @ptrCast(@alignCast(context));
- return &self.node;
+ return Element.Wrapper(Self, html).init(self);
}
fn fromNode(context: *anyopaque) Element {
@@ -67,10 +62,8 @@ fn Math(comptime template: []const u8) type {
return self.element();
}
- fn html(context: *anyopaque, alloc: Allocator) HTML.Error!HTML {
- const self: *Self = @ptrCast(@alignCast(context));
+ fn html(self: *Self, alloc: Allocator) HTML.Error!HTML {
const content = self.content orelse return (try HTML.Literal.init(alloc, "")).element();
-
var arena = std.heap.ArenaAllocator.init(alloc);
defer arena.deinit();
const escaped = try escape(arena.allocator(), content);
diff --git a/src/eval/paragraph.zig b/src/eval/paragraph.zig
index ca72142..3ebf29b 100644
--- a/src/eval/paragraph.zig
+++ b/src/eval/paragraph.zig
@@ -32,12 +32,7 @@ pub const Link = struct {
}
pub fn element(self: *Self) Element {
- return .{ .ptr = self, .vtable = .{ .html = html, .node = getNode } };
- }
-
- fn getNode(context: *anyopaque) *Node {
- const self: *Self = @ptrCast(@alignCast(context));
- return &self.node;
+ return Element.Wrapper(Self, html).init(self);
}
fn fromNode(context: *anyopaque) Element {
@@ -45,8 +40,7 @@ pub const Link = struct {
return self.element();
}
- fn html(context: *anyopaque, alloc: Allocator) HTML.Error!HTML {
- const self: *Self = @ptrCast(@alignCast(context));
+ fn html(self: *Self, alloc: Allocator) HTML.Error!HTML {
var el = try HTML.Content.init(alloc, "a");
el.content = try self.content.html(alloc);
try el.base.setAttribute("href", self.link);