aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/Element.zig243
-rw-r--r--src/content.zig4
-rw-r--r--src/eval/Element.zig136
-rw-r--r--src/eval/Title.zig45
-rw-r--r--src/eval/html/Element.zig (renamed from src/dom/Element.zig)0
-rw-r--r--src/eval/html/html.zig (renamed from src/dom/html.zig)0
-rw-r--r--src/eval/paragraph.zig79
-rw-r--r--src/link.zig5
-rw-r--r--src/paragraph.zig5
-rw-r--r--src/parser.zig2
-rw-r--r--src/testing.zig2
-rw-r--r--src/title.zig2
12 files changed, 271 insertions, 252 deletions
diff --git a/src/Element.zig b/src/Element.zig
deleted file mode 100644
index 7206125..0000000
--- a/src/Element.zig
+++ /dev/null
@@ -1,243 +0,0 @@
-const std = @import("std");
-const Allocator = std.mem.Allocator;
-const DOMElement = @import("dom/Element.zig");
-
-const Parent = @This();
-
-vtable: struct {
- deinit: *const fn (*anyopaque, Allocator) void,
- dom: *const fn (*anyopaque, Allocator) DOMElement.Error!DOMElement,
-},
-ptr: *anyopaque,
-
-pub fn renderHTML(self: Parent, alloc: Allocator) DOMElement.Error![]const u8 {
- var el = try self.vtable.dom(self.ptr, alloc);
- defer el.deinit();
- return el.render(alloc);
-}
-
-pub fn deinit(self: Parent, alloc: Allocator) void {
- self.vtable.deinit(self.ptr, alloc);
-}
-
-fn dom(self: Parent, alloc: Allocator) DOMElement.Error!DOMElement {
- return self.vtable.dom(self.ptr, alloc);
-}
-
-pub const Paragraph = Modifier("p");
-pub const Bold = Modifier("b");
-pub const Italic = Modifier("em");
-pub const Code = Modifier("code");
-
-pub const Empty = struct {
- content: std.ArrayList(Parent),
-
- const Self = @This();
-
- pub fn init(alloc: Allocator) !*Self {
- const v = try alloc.create(Self);
- v.* = .{ .content = try .initCapacity(alloc, 2) };
- return v;
- }
-
- pub fn element(self: *Self) Parent {
- return .{ .ptr = self, .vtable = .{ .deinit = destroy, .dom = Self.dom } };
- }
-
- pub fn deinit(self: *Self, alloc: Allocator) void {
- destroy(self, alloc);
- }
-
- fn destroy(context: *anyopaque, alloc: Allocator) void {
- const self: *Self = @ptrCast(@alignCast(context));
- for (self.content.items) |it| it.deinit(alloc);
- self.content.deinit(alloc);
- alloc.destroy(self);
- }
-
- fn dom(context: *anyopaque, alloc: Allocator) DOMElement.Error!DOMElement {
- const self: *Self = @ptrCast(@alignCast(context));
- var el = DOMElement.initEmpty(alloc);
- errdefer el.deinit();
- for (self.content.items) |it| try el.appendContent(try it.dom(alloc));
- return el;
- }
-};
-
-pub const Literal = struct {
- content: []const u8,
-
- const Self = @This();
-
- pub fn init(alloc: Allocator, content: []const u8) !*Self {
- const v = try alloc.create(Self);
- v.* = .{ .content = content };
- return v;
- }
-
- pub fn element(self: *Self) Parent {
- return .{ .ptr = self, .vtable = .{ .deinit = destroy, .dom = Self.dom } };
- }
-
- pub fn deinit(self: *Self, alloc: Allocator) void {
- destroy(self, alloc);
- }
-
- fn destroy(context: *anyopaque, alloc: Allocator) void {
- const self: *Self = @ptrCast(@alignCast(context));
- alloc.destroy(self);
- }
-
- fn dom(context: *anyopaque, alloc: Allocator) DOMElement.Error!DOMElement {
- const self: *Self = @ptrCast(@alignCast(context));
- return DOMElement.initLitEscaped(alloc, self.content);
- }
-};
-
-pub fn Modifier(comptime tag: []const u8) type {
- return struct {
- content: std.ArrayList(Parent),
-
- const Self = @This();
-
- pub fn init(alloc: Allocator) !*Self {
- const v = try alloc.create(Self);
- v.* = .{ .content = try .initCapacity(alloc, 2) };
- return v;
- }
-
- pub fn element(self: *Self) Parent {
- return .{ .ptr = self, .vtable = .{ .deinit = destroy, .dom = Self.dom } };
- }
-
- pub fn deinit(self: *Self, alloc: Allocator) void {
- destroy(self, alloc);
- }
-
- fn destroy(context: *anyopaque, alloc: Allocator) void {
- var self: *Self = @ptrCast(@alignCast(context));
- for (self.content.items) |it| it.deinit(alloc);
- self.content.deinit(alloc);
- alloc.destroy(self);
- }
-
- fn dom(context: *anyopaque, alloc: Allocator) DOMElement.Error!DOMElement {
- const self: *Self = @ptrCast(@alignCast(context));
- var el = try DOMElement.init(alloc, .content, tag);
- errdefer el.deinit();
- for (self.content.items) |it| try el.appendContent(try it.dom(alloc));
- return el;
- }
- };
-}
-
-pub const Link = struct {
- link: []const u8,
- content: Parent,
- target: ?[]const u8 = null,
-
- const Self = @This();
-
- pub fn init(alloc: Allocator, content: Parent, link: []const u8) !*Self {
- const v = try alloc.create(Self);
- v.* = .{
- .content = content,
- .link = link,
- };
- return v;
- }
-
- pub fn element(self: *Self) Parent {
- return .{ .ptr = self, .vtable = .{ .deinit = destroy, .dom = Self.dom } };
- }
-
- pub fn deinit(self: *Self, alloc: Allocator) void {
- destroy(self, alloc);
- }
-
- fn destroy(context: *anyopaque, alloc: Allocator) void {
- var self: *Self = @ptrCast(@alignCast(context));
- self.content.deinit(alloc);
- alloc.destroy(self);
- }
-
- fn dom(context: *anyopaque, alloc: Allocator) DOMElement.Error!DOMElement {
- const self: *Self = @ptrCast(@alignCast(context));
- var el = try DOMElement.init(alloc, .content, "a");
- errdefer el.deinit();
- try el.appendContent(try self.content.dom(alloc));
- try el.setAttribute("href", self.link);
- if (self.target) |target| try el.setAttribute("target", target);
- return el;
- }
-};
-
-pub const Title = struct {
- level: u3,
- content: Parent,
-
- const Self = @This();
-
- pub fn init(alloc: Allocator, level: u3, content: Parent) !*Self {
- const v = try alloc.create(Self);
- v.* = .{ .level = level, .content = content };
- return v;
- }
-
- pub fn element(self: *Self) Parent {
- return .{ .ptr = self, .vtable = .{ .deinit = destroy, .dom = Self.dom } };
- }
-
- pub fn deinit(self: *Self, alloc: Allocator) void {
- self.element().deinit(alloc);
- }
-
- fn destroy(context: *anyopaque, alloc: Allocator) void {
- var self: *Self = @ptrCast(@alignCast(context));
- self.content.deinit(alloc);
- alloc.destroy(self);
- }
-
- fn dom(context: *anyopaque, alloc: Allocator) DOMElement.Error!DOMElement {
- const self: *Self = @ptrCast(@alignCast(context));
- var el = try DOMElement.init(alloc, .content, switch (self.level) {
- 1 => "h1",
- 2 => "h2",
- 3 => "h3",
- 4 => "h4",
- 5 => "h5",
- 6 => "h6",
- else => unreachable,
- });
- errdefer el.deinit();
- try el.appendContent(try self.content.dom(alloc));
- return el;
- }
-};
-
-fn doTest(alloc: Allocator, el: Parent, exp: []const u8) !void {
- const got = try el.renderHTML(alloc);
- defer alloc.free(got);
- std.testing.expect(std.mem.eql(u8, got, exp)) catch |err| {
- std.debug.print("{s}\n", .{got});
- return err;
- };
-}
-
-test "paragraph" {
- const alloc = std.testing.allocator;
-
- const lit = (try Literal.init(alloc, "hello world")).element();
- try doTest(alloc, lit, "hello world");
-
- var p = try Paragraph.init(alloc);
- try p.content.append(alloc, lit);
- defer p.deinit(alloc);
- try doTest(alloc, p.element(), "<p>hello world</p>");
-
- const link = (try Link.init(alloc, (try Literal.init(alloc, "foo")).element(), "example.org")).element();
- try doTest(alloc, link, "<a href=\"example.org\">foo</a>");
-
- try p.content.append(alloc, link);
- try doTest(alloc, p.element(), "<p>hello world<a href=\"example.org\">foo</a></p>");
-}
diff --git a/src/content.zig b/src/content.zig
index 68d88ad..53f9418 100644
--- a/src/content.zig
+++ b/src/content.zig
@@ -2,7 +2,7 @@ const std = @import("std");
const Allocator = std.mem.Allocator;
const Token = @import("lexer/Token.zig");
const Lexer = @import("lexer/Lexer.zig");
-const Element = @import("Element.zig");
+const Element = @import("eval/Element.zig");
const parser = @import("parser.zig");
const link = @import("link.zig");
const testing = @import("testing.zig");
@@ -29,7 +29,7 @@ pub fn parse(alloc: Allocator, l: *Lexer) Error!Element {
}
fn parseModifier(alloc: Allocator, l: *Lexer, knd: Token.Kind, comptime tag: []const u8) Error!Element {
- var el = try Element.Modifier(tag).init(alloc);
+ var el = try Element.Simple(tag).init(alloc);
errdefer el.deinit(alloc);
while (l.peek()) |next| {
if (next.kind == knd) {
diff --git a/src/eval/Element.zig b/src/eval/Element.zig
new file mode 100644
index 0000000..e017bc5
--- /dev/null
+++ b/src/eval/Element.zig
@@ -0,0 +1,136 @@
+const std = @import("std");
+const Allocator = std.mem.Allocator;
+pub const HTML = @import("html/Element.zig");
+pub const Paragraph = struct {
+ const paragraph = @import("paragraph.zig");
+ pub const Block = paragraph.Block;
+ pub const Bold = paragraph.Bold;
+ pub const Code = paragraph.Code;
+ pub const Italic = paragraph.Italic;
+ pub const Link = paragraph.Link;
+};
+pub const Title = @import("Title.zig");
+
+const Element = @This();
+
+vtable: struct {
+ deinit: *const fn (*anyopaque, Allocator) void,
+ html: *const fn (*anyopaque, Allocator) HTML.Error!HTML,
+},
+ptr: *anyopaque,
+
+pub fn renderHTML(self: Element, alloc: Allocator) HTML.Error![]const u8 {
+ var el = try self.vtable.html(self.ptr, alloc);
+ defer el.deinit();
+ return el.render(alloc);
+}
+
+pub fn deinit(self: Element, alloc: Allocator) void {
+ self.vtable.deinit(self.ptr, alloc);
+}
+
+pub fn html(self: Element, alloc: Allocator) HTML.Error!HTML {
+ return self.vtable.html(self.ptr, alloc);
+}
+
+pub const Empty = struct {
+ content: std.ArrayList(Element),
+
+ const Self = @This();
+
+ pub fn init(alloc: Allocator) !*Self {
+ const v = try alloc.create(Self);
+ v.* = .{ .content = try .initCapacity(alloc, 2) };
+ return v;
+ }
+
+ pub fn element(self: *Self) Element {
+ return .{ .ptr = self, .vtable = .{ .deinit = destroy, .html = Self.html } };
+ }
+
+ pub fn deinit(self: *Self, alloc: Allocator) void {
+ destroy(self, alloc);
+ }
+
+ fn destroy(context: *anyopaque, alloc: Allocator) void {
+ const self: *Self = @ptrCast(@alignCast(context));
+ for (self.content.items) |it| it.deinit(alloc);
+ self.content.deinit(alloc);
+ alloc.destroy(self);
+ }
+
+ fn html(context: *anyopaque, alloc: Allocator) HTML.Error!HTML {
+ const self: *Self = @ptrCast(@alignCast(context));
+ var el = HTML.initEmpty(alloc);
+ errdefer el.deinit();
+ for (self.content.items) |it| try el.appendContent(try it.html(alloc));
+ return el;
+ }
+};
+
+pub const Literal = struct {
+ content: []const u8,
+
+ const Self = @This();
+
+ pub fn init(alloc: Allocator, content: []const u8) !*Self {
+ const v = try alloc.create(Self);
+ v.* = .{ .content = content };
+ return v;
+ }
+
+ pub fn element(self: *Self) Element {
+ return .{ .ptr = self, .vtable = .{ .deinit = destroy, .html = Self.html } };
+ }
+
+ pub fn deinit(self: *Self, alloc: Allocator) void {
+ destroy(self, alloc);
+ }
+
+ fn destroy(context: *anyopaque, alloc: Allocator) void {
+ const self: *Self = @ptrCast(@alignCast(context));
+ alloc.destroy(self);
+ }
+
+ fn html(context: *anyopaque, alloc: Allocator) HTML.Error!HTML {
+ const self: *Self = @ptrCast(@alignCast(context));
+ return HTML.initLitEscaped(alloc, self.content);
+ }
+};
+
+pub fn Simple(comptime tag: []const u8) type {
+ return struct {
+ content: std.ArrayList(Element),
+
+ const Self = @This();
+
+ pub fn init(alloc: Allocator) !*Self {
+ const v = try alloc.create(Self);
+ v.* = .{ .content = try .initCapacity(alloc, 2) };
+ return v;
+ }
+
+ pub fn element(self: *Self) Element {
+ return .{ .ptr = self, .vtable = .{ .deinit = destroy, .html = Self.html } };
+ }
+
+ pub fn deinit(self: *Self, alloc: Allocator) void {
+ destroy(self, alloc);
+ }
+
+ fn destroy(context: *anyopaque, alloc: Allocator) void {
+ var self: *Self = @ptrCast(@alignCast(context));
+ for (self.content.items) |it| it.deinit(alloc);
+ self.content.deinit(alloc);
+ alloc.destroy(self);
+ }
+
+ fn html(context: *anyopaque, alloc: Allocator) HTML.Error!HTML {
+ const self: *Self = @ptrCast(@alignCast(context));
+ var el = try HTML.init(alloc, .content, tag);
+ errdefer el.deinit();
+ for (self.content.items) |it| try el.appendContent(try it.html(alloc));
+ return el;
+ }
+ };
+}
diff --git a/src/eval/Title.zig b/src/eval/Title.zig
new file mode 100644
index 0000000..56524ad
--- /dev/null
+++ b/src/eval/Title.zig
@@ -0,0 +1,45 @@
+const std = @import("std");
+const Allocator = std.mem.Allocator;
+const HTML = Parent.HTML;
+const Parent = @import("Element.zig");
+
+level: u3,
+content: Parent,
+
+const Self = @This();
+
+pub fn init(alloc: Allocator, level: u3, content: Parent) !*Self {
+ const v = try alloc.create(Self);
+ v.* = .{ .level = level, .content = content };
+ return v;
+}
+
+pub fn element(self: *Self) Parent {
+ return .{ .ptr = self, .vtable = .{ .deinit = destroy, .html = html } };
+}
+
+pub fn deinit(self: *Self, alloc: Allocator) void {
+ self.element().deinit(alloc);
+}
+
+fn destroy(context: *anyopaque, alloc: Allocator) void {
+ var self: *Self = @ptrCast(@alignCast(context));
+ self.content.deinit(alloc);
+ alloc.destroy(self);
+}
+
+fn html(context: *anyopaque, alloc: Allocator) HTML.Error!HTML {
+ const self: *Self = @ptrCast(@alignCast(context));
+ var el = try HTML.init(alloc, .content, switch (self.level) {
+ 1 => "h1",
+ 2 => "h2",
+ 3 => "h3",
+ 4 => "h4",
+ 5 => "h5",
+ 6 => "h6",
+ else => unreachable,
+ });
+ errdefer el.deinit();
+ try el.appendContent(try self.content.html(alloc));
+ return el;
+}
diff --git a/src/dom/Element.zig b/src/eval/html/Element.zig
index 87fd876..87fd876 100644
--- a/src/dom/Element.zig
+++ b/src/eval/html/Element.zig
diff --git a/src/dom/html.zig b/src/eval/html/html.zig
index 064ebb1..064ebb1 100644
--- a/src/dom/html.zig
+++ b/src/eval/html/html.zig
diff --git a/src/eval/paragraph.zig b/src/eval/paragraph.zig
new file mode 100644
index 0000000..e56b7ff
--- /dev/null
+++ b/src/eval/paragraph.zig
@@ -0,0 +1,79 @@
+const std = @import("std");
+const Allocator = std.mem.Allocator;
+const HTML = Element.HTML;
+const Element = @import("Element.zig");
+
+pub const Block = Element.Simple("p");
+
+pub const Bold = Element.Simple("b");
+pub const Italic = Element.Simple("em");
+pub const Code = Element.Simple("code");
+
+
+pub const Link = struct {
+ link: []const u8,
+ content: Element,
+ target: ?[]const u8 = null,
+
+ const Self = @This();
+
+ pub fn init(alloc: Allocator, content: Element, link: []const u8) !*Self {
+ const v = try alloc.create(Self);
+ v.* = .{
+ .content = content,
+ .link = link,
+ };
+ return v;
+ }
+
+ pub fn element(self: *Self) Element {
+ return .{ .ptr = self, .vtable = .{ .deinit = destroy, .html = html } };
+ }
+
+ pub fn deinit(self: *Self, alloc: Allocator) void {
+ destroy(self, alloc);
+ }
+
+ fn destroy(context: *anyopaque, alloc: Allocator) void {
+ var self: *Self = @ptrCast(@alignCast(context));
+ self.content.deinit(alloc);
+ alloc.destroy(self);
+ }
+
+ fn html(context: *anyopaque, alloc: Allocator) HTML.Error!HTML {
+ const self: *Self = @ptrCast(@alignCast(context));
+ var el = try HTML.init(alloc, .content, "a");
+ errdefer el.deinit();
+ try el.appendContent(try self.content.html(alloc));
+ try el.setAttribute("href", self.link);
+ if (self.target) |target| try el.setAttribute("target", target);
+ return el;
+ }
+};
+
+fn doTest(alloc: Allocator, el: Element, exp: []const u8) !void {
+ const got = try el.renderHTML(alloc);
+ defer alloc.free(got);
+ std.testing.expect(std.mem.eql(u8, got, exp)) catch |err| {
+ std.debug.print("{s}\n", .{got});
+ return err;
+ };
+}
+
+test "paragraph" {
+ const alloc = std.testing.allocator;
+
+ const lit = (try Element.Literal.init(alloc, "hello world")).element();
+ try doTest(alloc, lit, "hello world");
+
+ var p = try Block.init(alloc);
+ try p.content.append(alloc, lit);
+ defer p.deinit(alloc);
+ try doTest(alloc, p.element(), "<p>hello world</p>");
+
+ const link = (try Link.init(alloc, (try Element.Literal.init(alloc, "foo")).element(), "example.org")).element();
+ try doTest(alloc, link, "<a href=\"example.org\">foo</a>");
+
+ try p.content.append(alloc, link);
+ try doTest(alloc, p.element(), "<p>hello world<a href=\"example.org\">foo</a></p>");
+}
diff --git a/src/link.zig b/src/link.zig
index 85156dc..e214b4b 100644
--- a/src/link.zig
+++ b/src/link.zig
@@ -3,7 +3,8 @@ const Allocator = std.mem.Allocator;
const eql = std.mem.eql;
const Token = @import("lexer/Token.zig");
const Lexer = @import("lexer/Lexer.zig");
-const Element = @import("Element.zig");
+const Element = @import("eval/Element.zig");
+const Link = Element.Paragraph.Link;
const content = @import("content.zig");
const testing = @import("testing.zig");
const doTest = testing.do;
@@ -16,7 +17,7 @@ pub fn parse(alloc: Allocator, l: *Lexer) Error!Element {
const second = data.second orelse return data.first.?;
var in = if (data.first) |first| first else (try Element.Literal.init(alloc, second)).element();
errdefer in.deinit(alloc);
- return (try Element.Link.init(alloc, in, data.second.?)).element();
+ return (try Link.init(alloc, in, data.second.?)).element();
}
pub const Data = struct {
diff --git a/src/paragraph.zig b/src/paragraph.zig
index 8edfa12..a76b98c 100644
--- a/src/paragraph.zig
+++ b/src/paragraph.zig
@@ -2,7 +2,8 @@ const std = @import("std");
const Allocator = std.mem.Allocator;
const Token = @import("lexer/Token.zig");
const Lexer = @import("lexer/Lexer.zig");
-const Element = @import("Element.zig");
+const Element = @import("eval/Element.zig");
+const Paragraph = Element.Paragraph;
const parser = @import("parser.zig");
const link = @import("link.zig");
const content = @import("content.zig");
@@ -13,7 +14,7 @@ const doTestError = testing.doError;
pub const Error = content.Error || link.Error || Lexer.Error || Allocator.Error;
pub fn parse(alloc: Allocator, l: *Lexer) Error!Element {
- var el = try Element.Paragraph.init(alloc);
+ var el = try Paragraph.Block.init(alloc);
errdefer el.deinit(alloc);
while (l.peek()) |next| {
switch (next.kind) {
diff --git a/src/parser.zig b/src/parser.zig
index 639160b..163c5a8 100644
--- a/src/parser.zig
+++ b/src/parser.zig
@@ -2,7 +2,7 @@ const std = @import("std");
const Allocator = std.mem.Allocator;
const Token = @import("lexer/Token.zig");
const Lexer = @import("lexer/Lexer.zig");
-const Element = @import("Element.zig");
+const Element = @import("eval/Element.zig");
const paragraph = @import("paragraph.zig");
const title = @import("title.zig");
const link = @import("link.zig");
diff --git a/src/testing.zig b/src/testing.zig
index 0911438..6d19e0e 100644
--- a/src/testing.zig
+++ b/src/testing.zig
@@ -1,7 +1,7 @@
const std = @import("std");
const Allocator = std.mem.Allocator;
const Lexer = @import("lexer/Lexer.zig");
-const Element = @import("Element.zig");
+const Element = @import("eval/Element.zig");
const parser = @import("parser.zig");
pub fn do(comptime parse: fn (Allocator, *Lexer) parser.Error!Element, alloc: Allocator, t: []const u8, v: []const u8) !void {
diff --git a/src/title.zig b/src/title.zig
index 506af21..9fdc116 100644
--- a/src/title.zig
+++ b/src/title.zig
@@ -2,7 +2,7 @@ const std = @import("std");
const Allocator = std.mem.Allocator;
const Token = @import("lexer/Token.zig");
const Lexer = @import("lexer/Lexer.zig");
-const Element = @import("Element.zig");
+const Element = @import("eval/Element.zig");
const paragraph = @import("paragraph.zig");
const testing = @import("testing.zig");
const doTest = testing.do;