mirror of
https://github.com/lightpanda-io/browser.git
synced 2026-03-22 12:44:43 +00:00
Fix a few more cases
From dom/nodes/ParentNode-querySelector-escapes.html
This commit is contained in:
@@ -294,3 +294,12 @@
|
|||||||
testing.expectEqual('Non-ASCII class 1', document.querySelector('div.café').textContent);
|
testing.expectEqual('Non-ASCII class 1', document.querySelector('div.café').textContent);
|
||||||
testing.expectEqual('Non-ASCII ID 1', document.querySelector('span#niño').textContent);
|
testing.expectEqual('Non-ASCII ID 1', document.querySelector('span#niño').textContent);
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
|
<span id=".,:!">Punctuation test</span>
|
||||||
|
|
||||||
|
<script id=escapedPunctuation>
|
||||||
|
{
|
||||||
|
// Test escaped punctuation in ID selectors
|
||||||
|
testing.expectEqual('Punctuation test', document.querySelector('#\\.\\,\\:\\!').textContent);
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|||||||
@@ -49,29 +49,71 @@ const ParseError = error{
|
|||||||
StringTooLarge,
|
StringTooLarge,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// CSS Syntax preprocessing: normalize line endings (CRLF → LF, CR → LF)
|
||||||
|
// https://drafts.csswg.org/css-syntax/#input-preprocessing
|
||||||
|
fn preprocessInput(arena: Allocator, input: []const u8) ![]const u8 {
|
||||||
|
var i = std.mem.indexOfScalar(u8, input, '\r') orelse return input;
|
||||||
|
|
||||||
|
var result = try std.ArrayList(u8).initCapacity(arena, input.len);
|
||||||
|
result.appendSliceAssumeCapacity(input[0..i]);
|
||||||
|
|
||||||
|
while (i < input.len) {
|
||||||
|
const c = input[i];
|
||||||
|
if (c == '\r') {
|
||||||
|
result.appendAssumeCapacity('\n');
|
||||||
|
i += 1;
|
||||||
|
if (i < input.len and input[i] == '\n') {
|
||||||
|
i += 1;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
result.appendAssumeCapacity(c);
|
||||||
|
i += 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return result.items;
|
||||||
|
}
|
||||||
|
|
||||||
pub fn parseList(arena: Allocator, input: []const u8, page: *Page) ParseError![]const Selector.Selector {
|
pub fn parseList(arena: Allocator, input: []const u8, page: *Page) ParseError![]const Selector.Selector {
|
||||||
|
// Preprocess input to normalize line endings
|
||||||
|
const preprocessed = try preprocessInput(arena, input);
|
||||||
|
|
||||||
var selectors: std.ArrayList(Selector.Selector) = .empty;
|
var selectors: std.ArrayList(Selector.Selector) = .empty;
|
||||||
|
|
||||||
var remaining = input;
|
var remaining = preprocessed;
|
||||||
while (true) {
|
while (true) {
|
||||||
const trimmed = std.mem.trimLeft(u8, remaining, &std.ascii.whitespace);
|
const trimmed = std.mem.trimLeft(u8, remaining, &std.ascii.whitespace);
|
||||||
if (trimmed.len == 0) break;
|
if (trimmed.len == 0) break;
|
||||||
|
|
||||||
var comma_pos: usize = trimmed.len;
|
var comma_pos: usize = trimmed.len;
|
||||||
var depth: usize = 0;
|
var depth: usize = 0;
|
||||||
for (trimmed, 0..) |c, i| {
|
var i: usize = 0;
|
||||||
|
while (i < trimmed.len) {
|
||||||
|
const c = trimmed[i];
|
||||||
switch (c) {
|
switch (c) {
|
||||||
'(' => depth += 1,
|
'\\' => {
|
||||||
|
// Skip escape sequence (backslash + next character)
|
||||||
|
i += 1;
|
||||||
|
if (i < trimmed.len) i += 1;
|
||||||
|
},
|
||||||
|
'(' => {
|
||||||
|
depth += 1;
|
||||||
|
i += 1;
|
||||||
|
},
|
||||||
')' => {
|
')' => {
|
||||||
if (depth > 0) depth -= 1;
|
if (depth > 0) depth -= 1;
|
||||||
|
i += 1;
|
||||||
},
|
},
|
||||||
',' => {
|
',' => {
|
||||||
if (depth == 0) {
|
if (depth == 0) {
|
||||||
comma_pos = i;
|
comma_pos = i;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
i += 1;
|
||||||
|
},
|
||||||
|
else => {
|
||||||
|
i += 1;
|
||||||
},
|
},
|
||||||
else => {},
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user