@@ -13,14 +13,38 @@ const NodeFilter = @import("NodeFilter.zig");
1313const DOMTreeWalker = @import ("DOMTreeWalker.zig" );
1414const DOMNodeIterator = @import ("DOMNodeIterator.zig" );
1515
16+ pub const HTMLDocument = @import ("HTMLDocument.zig" );
17+
1618const Document = @This ();
1719
20+ _type : Type ,
1821_proto : * Node ,
1922_location : ? * Location = null ,
2023_ready_state : ReadyState = .loading ,
2124_current_script : ? * Element.Html.Script = null ,
2225_elements_by_id : std .StringHashMapUnmanaged (* Element ) = .empty ,
2326
27+ pub const Type = union (enum ) {
28+ generic ,
29+ html : * HTMLDocument ,
30+ };
31+
32+ pub fn is (self : * Document , comptime T : type ) ? * T {
33+ switch (self ._type ) {
34+ .html = > | html | {
35+ if (T == HTMLDocument ) {
36+ return html ;
37+ }
38+ },
39+ .generic = > {},
40+ }
41+ return null ;
42+ }
43+
44+ pub fn as (self : * Document , comptime T : type ) * T {
45+ return self .is (T ).? ;
46+ }
47+
2448pub fn asNode (self : * Document ) * Node {
2549 return self ._proto ;
2650}
@@ -33,14 +57,6 @@ pub fn getURL(_: *const Document, page: *const Page) [:0]const u8 {
3357 return page .url ;
3458}
3559
36- pub fn getReadyState (self : * const Document ) []const u8 {
37- return @tagName (self ._ready_state );
38- }
39-
40- pub fn getCurrentScript (self : * const Document ) ? * Element.Html.Script {
41- return self ._current_script ;
42- }
43-
4460pub fn createElement (_ : * const Document , name : []const u8 , page : * Page ) ! * Element {
4561 const node = try page .createElement (null , name , null );
4662 return node .as (Element );
@@ -70,13 +86,13 @@ pub fn getElementsByTagName(self: *Document, tag_name: []const u8, page: *Page)
7086 if (Node .Element .Tag .parseForMatch (lower )) | known | {
7187 // optimized for known tag names, comparis
7288 return .{
73- .tag = try collections .NodeLive (.tag ).init (null , self .asNode (), known , page ),
89+ .tag = collections .NodeLive (.tag ).init (null , self .asNode (), known , page ),
7490 };
7591 }
7692
7793 const arena = page .arena ;
7894 const filter = try String .init (arena , lower , .{});
79- return .{ .tag_name = try collections .NodeLive (.tag_name ).init (arena , self .asNode (), filter , page ) };
95+ return .{ .tag_name = collections .NodeLive (.tag_name ).init (arena , self .asNode (), filter , page ) };
8096}
8197
8298pub fn getElementsByClassName (self : * Document , class_name : []const u8 , page : * Page ) ! collections. NodeLive (.class_name ) {
@@ -96,46 +112,6 @@ pub fn getDocumentElement(self: *Document) ?*Element {
96112 return null ;
97113}
98114
99- pub fn getImages (self : * Document , page : * Page ) ! collections. NodeLive (.tag ) {
100- return collections .NodeLive (.tag ).init (null , self .asNode (), .img , page );
101- }
102-
103- pub fn getScripts (self : * Document , page : * Page ) ! collections. NodeLive (.tag ) {
104- return collections .NodeLive (.tag ).init (null , self .asNode (), .script , page );
105- }
106-
107- pub fn getForms (self : * Document , page : * Page ) ! collections. NodeLive (.tag ) {
108- return collections .NodeLive (.tag ).init (null , self .asNode (), .form , page );
109- }
110-
111- pub fn getLinks (self : * Document , page : * Page ) ! collections. NodeLive (.tag ) {
112- return collections .NodeLive (.tag ).init (null , self .asNode (), .anchor , page );
113- }
114-
115- pub fn getHead (self : * Document ) ? * Element.Html.Head {
116- const doc_el = self .getDocumentElement () orelse return null ;
117- var child = doc_el .asNode ().firstChild ();
118- while (child ) | node | {
119- if (node .is (Element .Html .Head )) | head | {
120- return head ;
121- }
122- child = node .nextSibling ();
123- }
124- return null ;
125- }
126-
127- pub fn getBody (self : * Document ) ? * Element.Html.Body {
128- const doc_el = self .getDocumentElement () orelse return null ;
129- var child = doc_el .asNode ().firstChild ();
130- while (child ) | node | {
131- if (node .is (Element .Html .Body )) | body | {
132- return body ;
133- }
134- child = node .nextSibling ();
135- }
136- return null ;
137- }
138-
139115pub fn querySelector (self : * Document , input : []const u8 , page : * Page ) ! ? * Element {
140116 return Selector .querySelector (self .asNode (), input , page );
141117}
@@ -160,43 +136,18 @@ pub fn createTextNode(_: *const Document, data: []const u8, page: *Page) !*Node
160136 return page .createTextNode (data );
161137}
162138
163- pub fn getLocation (self : * const Document ) ? * Location {
164- return self ._location ;
165- }
166-
167- // @ZIGDOM what_to_show tristate (null vs undefined vs value)
168139pub fn createTreeWalker (_ : * const Document , root : * Node , what_to_show : ? u32 , filter : ? DOMTreeWalker.FilterOpts , page : * Page ) ! * DOMTreeWalker {
169140 const show = what_to_show orelse NodeFilter .SHOW_ALL ;
170141 return DOMTreeWalker .init (root , show , filter , page );
171142}
172143
173- // @ZIGDOM what_to_show tristate (null vs undefined vs value)
174144pub fn createNodeIterator (_ : * const Document , root : * Node , what_to_show : ? u32 , filter : ? DOMNodeIterator.FilterOpts , page : * Page ) ! * DOMNodeIterator {
175145 const show = what_to_show orelse NodeFilter .SHOW_ALL ;
176146 return DOMNodeIterator .init (root , show , filter , page );
177147}
178148
179- pub fn getTitle (self : * Document , page : * Page ) ! []const u8 {
180- const head = self .getHead () orelse return "" ;
181- var it = head .asNode ().childrenIterator ();
182- while (it .next ()) | node | {
183- if (node .is (Element .Html .Title )) | title | {
184- var buf = std .Io .Writer .Allocating .init (page .call_arena );
185- try title .asElement ().getInnerText (& buf .writer );
186- return buf .written ();
187- }
188- }
189- return "" ;
190- }
191-
192- pub fn setTitle (self : * Document , title : []const u8 , page : * Page ) ! void {
193- const head = self .getHead () orelse return ;
194- var it = head .asNode ().childrenIterator ();
195- while (it .next ()) | node | {
196- if (node .is (Element .Html .Title )) | title_element | {
197- return title_element .asElement ().replaceChildren (&.{.{ .text = title }}, page );
198- }
199- }
149+ pub fn getReadyState (self : * const Document ) []const u8 {
150+ return @tagName (self ._ready_state );
200151}
201152
202153const ReadyState = enum {
@@ -216,20 +167,14 @@ pub const JsApi = struct {
216167
217168 pub const constructor = bridge .constructor (_constructor , .{});
218169 fn _constructor (page : * Page ) ! * Document {
219- return page ._factory .node (Document { ._proto = undefined });
170+ return page ._factory .node (Document {
171+ ._proto = undefined ,
172+ ._type = .generic ,
173+ });
220174 }
221175
222176 pub const URL = bridge .accessor (Document .getURL , null , .{});
223- pub const currentScript = bridge .accessor (Document .getCurrentScript , null , .{});
224- pub const head = bridge .accessor (Document .getHead , null , .{});
225- pub const body = bridge .accessor (Document .getBody , null , .{});
226- pub const title = bridge .accessor (Document .getTitle , Document .setTitle , .{});
227177 pub const documentElement = bridge .accessor (Document .getDocumentElement , null , .{});
228- pub const images = bridge .accessor (Document .getImages , null , .{});
229- pub const scripts = bridge .accessor (Document .getScripts , null , .{});
230- pub const links = bridge .accessor (Document .getLinks , null , .{});
231- pub const forms = bridge .accessor (Document .getForms , null , .{});
232- pub const location = bridge .accessor (Document .getLocation , null , .{ .cache = "location" });
233178 pub const readyState = bridge .accessor (Document .getReadyState , null , .{});
234179
235180 pub const createElement = bridge .function (Document .createElement , .{});
0 commit comments