diff --git a/src/browser/css/Parser.zig b/src/browser/css/Parser.zig index 053e9435..401baecb 100644 --- a/src/browser/css/Parser.zig +++ b/src/browser/css/Parser.zig @@ -318,12 +318,6 @@ pub const RulesIterator = struct { var selector_start: ?usize = null; var selector_end: ?usize = null; - // Skip leading trivia - while (self.stream.peek()) |peeked| { - if (!isWhitespaceOrComment(peeked.token)) break; - _ = self.stream.next(); - } - while (true) { const peeked = self.stream.peek() orelse return null; @@ -370,6 +364,11 @@ pub const RulesIterator = struct { continue; } + if (selector_start == null and (isWhitespaceOrComment(peeked.token) or isSemicolon(peeked.token))) { + _ = self.stream.next(); + continue; + } + const span = self.stream.next() orelse return null; if (!isWhitespaceOrComment(span.token)) { if (selector_start == null) selector_start = span.start; @@ -470,3 +469,13 @@ test "RulesIterator: comments and whitespace" { try testing.expectEqualStrings(" /* comment */ color: red; ", rule.block); try testing.expectEqual(@as(?Rule, null), it.next()); } + +test "RulesIterator: top-level semicolons" { + var it = RulesIterator.init("*{}; ; p{}"); + var rule = it.next() orelse return error.MissingRule; + try testing.expectEqualStrings("*", rule.selector); + + rule = it.next() orelse return error.MissingRule; + try testing.expectEqualStrings("p", rule.selector); + try testing.expectEqual(@as(?Rule, null), it.next()); +} diff --git a/src/browser/tests/css/stylesheet.html b/src/browser/tests/css/stylesheet.html index 8e284e66..41ed60df 100644 --- a/src/browser/tests/css/stylesheet.html +++ b/src/browser/tests/css/stylesheet.html @@ -468,6 +468,18 @@ } + +