mirror of
https://github.com/lightpanda-io/browser.git
synced 2025-10-28 22:53:28 +00:00
css: matcher draft
This commit is contained in:
@@ -11,6 +11,37 @@ pub fn parse(alloc: std.mem.Allocator, s: []const u8, opts: parser.ParseOptions)
|
||||
return p.parse(alloc);
|
||||
}
|
||||
|
||||
// matchFirst call m.match with the first node that matches the selector s, from the
|
||||
// descendants of n and returns true. If none matches, it returns false.
|
||||
pub fn matchFirst(s: Selector, node: anytype, m: anytype) !bool {
|
||||
var c = try node.firstChild();
|
||||
while (true) {
|
||||
if (c == null) break;
|
||||
|
||||
if (try s.match(c.?)) {
|
||||
try m.match(c.?);
|
||||
return true;
|
||||
}
|
||||
|
||||
if (try matchFirst(s, c.?, m)) return true;
|
||||
c = try c.?.nextSibling();
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
// matchAll call m.match with the all the nodes that matches the selector s, from the
|
||||
// descendants of n.
|
||||
pub fn matchAll(s: Selector, node: anytype, m: anytype) !void {
|
||||
var c = try node.firstChild();
|
||||
while (true) {
|
||||
if (c == null) break;
|
||||
|
||||
if (try s.match(c.?)) try m.match(c.?);
|
||||
try matchFirst(s, c.?, m);
|
||||
c = try c.?.nextSibling();
|
||||
}
|
||||
}
|
||||
|
||||
test "parse" {
|
||||
const alloc = std.testing.allocator;
|
||||
|
||||
|
||||
22
src/css/libdom.zig
Normal file
22
src/css/libdom.zig
Normal file
@@ -0,0 +1,22 @@
|
||||
const std = @import("std");
|
||||
|
||||
const parser = @import("../netsurf.zig");
|
||||
|
||||
// Node implementation with Netsurf Libdom C lib.
|
||||
pub const Node = struct {
|
||||
node: *parser.Node,
|
||||
|
||||
pub fn firstChild(n: Node) !?Node {
|
||||
const c = try parser.nodeFirstChild(n.node);
|
||||
if (c) |cc| return .{ .node = cc };
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
pub fn nextSibling(n: Node) ?Node {
|
||||
const c = try parser.nodeNextSibling(n.node);
|
||||
if (c) |cc| return .{ .node = cc };
|
||||
|
||||
return null;
|
||||
}
|
||||
};
|
||||
61
src/css/match_test.zig
Normal file
61
src/css/match_test.zig
Normal file
@@ -0,0 +1,61 @@
|
||||
const std = @import("std");
|
||||
const css = @import("css.zig");
|
||||
|
||||
// Node mock implementation for test only.
|
||||
pub const Node = struct {
|
||||
child: ?*const Node = null,
|
||||
sibling: ?*const Node = null,
|
||||
|
||||
name: []const u8 = "",
|
||||
|
||||
pub fn firstChild(n: *const Node) !?*const Node {
|
||||
return n.child;
|
||||
}
|
||||
|
||||
pub fn nextSibling(n: *const Node) !?*const Node {
|
||||
return n.sibling;
|
||||
}
|
||||
|
||||
pub fn tag(n: *const Node) ![]const u8 {
|
||||
return n.name;
|
||||
}
|
||||
};
|
||||
const Matcher = struct {
|
||||
const Nodes = std.ArrayList(*const Node);
|
||||
|
||||
nodes: Nodes,
|
||||
|
||||
fn init(alloc: std.mem.Allocator) Matcher {
|
||||
return .{ .nodes = Nodes.init(alloc) };
|
||||
}
|
||||
|
||||
fn deinit(m: *Matcher) void {
|
||||
m.nodes.deinit();
|
||||
}
|
||||
|
||||
fn reset(m: *Matcher) void {
|
||||
m.nodes.clearRetainingCapacity();
|
||||
}
|
||||
|
||||
pub fn match(m: *Matcher, n: *const Node) !void {
|
||||
try m.nodes.append(n);
|
||||
}
|
||||
};
|
||||
|
||||
test "matchFirst" {
|
||||
const alloc = std.testing.allocator;
|
||||
|
||||
const s = try css.parse(alloc, "address", .{});
|
||||
defer s.deinit(alloc);
|
||||
|
||||
var matcher = Matcher.init(alloc);
|
||||
defer matcher.deinit();
|
||||
|
||||
const node: Node = .{
|
||||
.child = &.{ .name = "address" },
|
||||
};
|
||||
|
||||
_ = try css.matchFirst(s, &node, &matcher);
|
||||
try std.testing.expect(1 == matcher.nodes.items.len);
|
||||
try std.testing.expect(matcher.nodes.items[0] == node.child);
|
||||
}
|
||||
@@ -165,6 +165,13 @@ pub const Selector = union(enum) {
|
||||
},
|
||||
pseudo_element: PseudoClass,
|
||||
|
||||
pub fn match(s: Selector, n: anytype) !bool {
|
||||
return switch (s) {
|
||||
.tag => |v| std.ascii.eqlIgnoreCase(v, try n.tag()),
|
||||
else => false,
|
||||
};
|
||||
}
|
||||
|
||||
pub fn deinit(sel: Selector, alloc: std.mem.Allocator) void {
|
||||
switch (sel) {
|
||||
.group => |v| {
|
||||
|
||||
Reference in New Issue
Block a user