Skip to content

Commit 269dcf0

Browse files
authored
Merge pull request #806 from lightpanda-io/document-range
add AbstractRange and Range
2 parents 997ec7f + ce638c3 commit 269dcf0

File tree

3 files changed

+126
-0
lines changed

3 files changed

+126
-0
lines changed

src/browser/dom/document.zig

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@ const css = @import("css.zig");
3232
const Element = @import("element.zig").Element;
3333
const ElementUnion = @import("element.zig").Union;
3434
const TreeWalker = @import("tree_walker.zig").TreeWalker;
35+
const Range = @import("range.zig").Range;
3536

3637
const Env = @import("../env.zig").Env;
3738

@@ -290,6 +291,10 @@ pub const Document = struct {
290291
const state = try page.getOrCreateNodeState(@alignCast(@ptrCast(self)));
291292
state.active_element = @ptrCast(e);
292293
}
294+
295+
pub fn _createRange(_: *parser.Document) Range {
296+
return Range.constructor();
297+
}
293298
};
294299

295300
const testing = @import("../../testing.zig");

src/browser/dom/dom.zig

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -47,4 +47,5 @@ pub const Interfaces = .{
4747
NodeFilter,
4848
@import("performance.zig").Interfaces,
4949
PerformanceObserver,
50+
@import("range.zig").Interfaces,
5051
};

src/browser/dom/range.zig

Lines changed: 120 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,120 @@
1+
// Copyright (C) 2023-2024 Lightpanda (Selecy SAS)
2+
//
3+
// Francis Bouvier <francis@lightpanda.io>
4+
// Pierre Tachoire <pierre@lightpanda.io>
5+
//
6+
// This program is free software: you can redistribute it and/or modify
7+
// it under the terms of the GNU Affero General Public License as
8+
// published by the Free Software Foundation, either version 3 of the
9+
// License, or (at your option) any later version.
10+
//
11+
// This program is distributed in the hope that it will be useful,
12+
// but WITHOUT ANY WARRANTY; without even the implied warranty of
13+
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14+
// GNU Affero General Public License for more details.
15+
//
16+
// You should have received a copy of the GNU Affero General Public License
17+
// along with this program. If not, see <https://www.gnu.org/licenses/>.
18+
19+
const std = @import("std");
20+
21+
const parser = @import("../netsurf.zig");
22+
const Page = @import("../page.zig").Page;
23+
24+
pub const Interfaces = .{
25+
AbstractRange,
26+
Range,
27+
};
28+
29+
pub const AbstractRange = struct {
30+
collapsed: bool,
31+
end_container: *parser.Node,
32+
end_offset: i32,
33+
start_container: *parser.Node,
34+
start_offset: i32,
35+
36+
pub fn updateCollapsed(self: *AbstractRange) void {
37+
// TODO: Eventually, compare properly.
38+
self.collapsed = false;
39+
}
40+
41+
pub fn get_collapsed(self: *const AbstractRange) bool {
42+
return self.collapsed;
43+
}
44+
45+
pub fn get_endContainer(self: *const AbstractRange) *parser.Node {
46+
return self.end_container;
47+
}
48+
49+
pub fn get_endOffset(self: *const AbstractRange) i32 {
50+
return self.end_offset;
51+
}
52+
53+
pub fn get_startContainer(self: *const AbstractRange) *parser.Node {
54+
return self.start_container;
55+
}
56+
57+
pub fn get_startOffset(self: *const AbstractRange) i32 {
58+
return self.start_offset;
59+
}
60+
};
61+
62+
pub const Range = struct {
63+
pub const prototype = *AbstractRange;
64+
65+
proto: AbstractRange,
66+
67+
pub fn constructor() Range {
68+
const proto: AbstractRange = .{
69+
.collapsed = true,
70+
.end_container = undefined,
71+
.end_offset = 0,
72+
.start_container = undefined,
73+
.start_offset = 0,
74+
};
75+
76+
return .{ .proto = proto };
77+
}
78+
79+
pub fn _setStart(self: *Range, node: *parser.Node, offset: i32) void {
80+
self.proto.start_container = node;
81+
self.proto.start_offset = offset;
82+
self.proto.updateCollapsed();
83+
}
84+
85+
pub fn _setEnd(self: *Range, node: *parser.Node, offset: i32) void {
86+
self.proto.end_container = node;
87+
self.proto.end_offset = offset;
88+
self.proto.updateCollapsed();
89+
}
90+
91+
pub fn _createContextualFragment(_: *Range, fragment: []const u8, page: *Page) !*parser.DocumentFragment {
92+
const document_html = page.window.document;
93+
const document = parser.documentHTMLToDocument(document_html);
94+
const doc_frag = try parser.documentParseFragmentFromStr(document, fragment);
95+
return doc_frag;
96+
}
97+
};
98+
99+
const testing = @import("../../testing.zig");
100+
test "Browser.Range" {
101+
var runner = try testing.jsRunner(testing.tracking_allocator, .{});
102+
defer runner.deinit();
103+
104+
try runner.testCases(&.{
105+
// Test Range constructor
106+
.{ "let range = new Range()", "undefined" },
107+
.{ "range instanceof Range", "true" },
108+
.{ "range instanceof AbstractRange", "true" },
109+
110+
// Test initial state - collapsed range
111+
.{ "range.collapsed", "true" },
112+
.{ "range.startOffset", "0" },
113+
.{ "range.endOffset", "0" },
114+
115+
// Test document.createRange()
116+
.{ "let docRange = document.createRange()", "undefined" },
117+
.{ "docRange instanceof Range", "true" },
118+
.{ "docRange.collapsed", "true" },
119+
}, .{});
120+
}

0 commit comments

Comments
 (0)