mirror of
https://github.com/lightpanda-io/browser.git
synced 2025-12-17 08:48:58 +00:00
css: add pseudo class relative match
This commit is contained in:
@@ -176,6 +176,31 @@ test "matchFirst" {
|
|||||||
} } } },
|
} } } },
|
||||||
.exp = 1,
|
.exp = 1,
|
||||||
},
|
},
|
||||||
|
.{
|
||||||
|
.q = ":not(p)",
|
||||||
|
.n = .{ .child = &.{ .name = "p", .child = &.{ .name = "a" }, .sibling = &.{ .name = "strong" } } },
|
||||||
|
.exp = 1,
|
||||||
|
},
|
||||||
|
.{
|
||||||
|
.q = "p:has(a)",
|
||||||
|
.n = .{ .child = &.{ .name = "p", .child = &.{ .name = "a" }, .sibling = &.{ .name = "strong" } } },
|
||||||
|
.exp = 1,
|
||||||
|
},
|
||||||
|
.{
|
||||||
|
.q = "p:has(strong)",
|
||||||
|
.n = .{ .child = &.{ .name = "p", .child = &.{ .name = "a" }, .sibling = &.{ .name = "strong" } } },
|
||||||
|
.exp = 0,
|
||||||
|
},
|
||||||
|
.{
|
||||||
|
.q = "p:haschild(a)",
|
||||||
|
.n = .{ .child = &.{ .name = "p", .child = &.{ .name = "a" }, .sibling = &.{ .name = "strong" } } },
|
||||||
|
.exp = 1,
|
||||||
|
},
|
||||||
|
.{
|
||||||
|
.q = "p:haschild(strong)",
|
||||||
|
.n = .{ .child = &.{ .name = "p", .child = &.{ .name = "a" }, .sibling = &.{ .name = "strong" } } },
|
||||||
|
.exp = 0,
|
||||||
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
for (testcases) |tc| {
|
for (testcases) |tc| {
|
||||||
@@ -315,6 +340,31 @@ test "matchAll" {
|
|||||||
} } } },
|
} } } },
|
||||||
.exp = 1,
|
.exp = 1,
|
||||||
},
|
},
|
||||||
|
.{
|
||||||
|
.q = ":not(p)",
|
||||||
|
.n = .{ .child = &.{ .name = "p", .child = &.{ .name = "a" }, .sibling = &.{ .name = "strong" } } },
|
||||||
|
.exp = 2,
|
||||||
|
},
|
||||||
|
.{
|
||||||
|
.q = "p:has(a)",
|
||||||
|
.n = .{ .child = &.{ .name = "p", .child = &.{ .name = "a" }, .sibling = &.{ .name = "strong" } } },
|
||||||
|
.exp = 1,
|
||||||
|
},
|
||||||
|
.{
|
||||||
|
.q = "p:has(strong)",
|
||||||
|
.n = .{ .child = &.{ .name = "p", .child = &.{ .name = "a" }, .sibling = &.{ .name = "strong" } } },
|
||||||
|
.exp = 0,
|
||||||
|
},
|
||||||
|
.{
|
||||||
|
.q = "p:haschild(a)",
|
||||||
|
.n = .{ .child = &.{ .name = "p", .child = &.{ .name = "a" }, .sibling = &.{ .name = "strong" } } },
|
||||||
|
.exp = 1,
|
||||||
|
},
|
||||||
|
.{
|
||||||
|
.q = "p:haschild(strong)",
|
||||||
|
.n = .{ .child = &.{ .name = "p", .child = &.{ .name = "a" }, .sibling = &.{ .name = "strong" } } },
|
||||||
|
.exp = 0,
|
||||||
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
for (testcases) |tc| {
|
for (testcases) |tc| {
|
||||||
|
|||||||
@@ -143,6 +143,7 @@ pub const PseudoClass = enum {
|
|||||||
pub const Selector = union(enum) {
|
pub const Selector = union(enum) {
|
||||||
pub const Error = error{
|
pub const Error = error{
|
||||||
UnknownCombinedCombinator,
|
UnknownCombinedCombinator,
|
||||||
|
UnsupportedRelativePseudoClass,
|
||||||
};
|
};
|
||||||
|
|
||||||
compound: struct {
|
compound: struct {
|
||||||
@@ -289,10 +290,41 @@ pub const Selector = union(enum) {
|
|||||||
};
|
};
|
||||||
},
|
},
|
||||||
.never_match => return false,
|
.never_match => return false,
|
||||||
|
.pseudo_class_relative => |v| {
|
||||||
|
if (!n.isElement()) return false;
|
||||||
|
|
||||||
|
return switch (v.pseudo_class) {
|
||||||
|
.not => !try v.match.match(n),
|
||||||
|
.has => try hasDescendantMatch(v.match, n),
|
||||||
|
.haschild => try hasChildMatch(v.match, n),
|
||||||
|
else => Error.UnsupportedRelativePseudoClass,
|
||||||
|
};
|
||||||
|
},
|
||||||
else => false,
|
else => false,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn hasDescendantMatch(s: *const Selector, n: anytype) anyerror!bool {
|
||||||
|
var c = try n.firstChild();
|
||||||
|
while (c != null) {
|
||||||
|
if (try s.match(c.?)) return true;
|
||||||
|
if (c.?.isElement() and try hasDescendantMatch(s, c.?)) return true;
|
||||||
|
c = try c.?.nextSibling();
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
fn hasChildMatch(s: *const Selector, n: anytype) anyerror!bool {
|
||||||
|
var c = try n.firstChild();
|
||||||
|
while (c != null) {
|
||||||
|
if (try s.match(c.?)) return true;
|
||||||
|
c = try c.?.nextSibling();
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
pub fn deinit(sel: Selector, alloc: std.mem.Allocator) void {
|
pub fn deinit(sel: Selector, alloc: std.mem.Allocator) void {
|
||||||
switch (sel) {
|
switch (sel) {
|
||||||
.group => |v| {
|
.group => |v| {
|
||||||
|
|||||||
Reference in New Issue
Block a user