1 /*
2  * Copyright (C) 2018-2021 Alexander Borisov
3  *
4  * Author: Alexander Borisov <borisov@lexbor.com>
5  */
6 
7 #ifndef LEXBOR_HTML_DOCUMENT_H
8 #define LEXBOR_HTML_DOCUMENT_H
9 
10 #ifdef __cplusplus
11 extern "C" {
12 #endif
13 
14 #include "lexbor/core/mraw.h"
15 #include "lexbor/core/avl.h"
16 
17 #include "lexbor/tag/tag.h"
18 #include "lexbor/ns/ns.h"
19 #include "lexbor/html/interface.h"
20 #include "lexbor/dom/interfaces/attr.h"
21 #include "lexbor/dom/interfaces/document.h"
22 #include "lexbor/css/css.h"
23 
24 
25 typedef lxb_status_t
26 (*lxb_html_document_done_cb_f)(lxb_html_document_t *document);
27 
28 typedef unsigned int lxb_html_document_opt_t;
29 
30 typedef enum {
31     LXB_HTML_DOCUMENT_READY_STATE_UNDEF       = 0x00,
32     LXB_HTML_DOCUMENT_READY_STATE_LOADING     = 0x01,
33     LXB_HTML_DOCUMENT_READY_STATE_INTERACTIVE = 0x02,
34     LXB_HTML_DOCUMENT_READY_STATE_COMPLETE    = 0x03,
35 }
36 lxb_html_document_ready_state_t;
37 
38 enum lxb_html_document_opt {
39     LXB_HTML_DOCUMENT_OPT_UNDEF     = 0x00,
40     LXB_HTML_DOCUMENT_PARSE_WO_COPY = 0x01
41 };
42 
43 typedef struct {
44     lxb_css_memory_t    *memory;
45     lxb_css_selectors_t *css_selectors;
46     lxb_css_parser_t    *parser;
47 
48     lexbor_avl_t        *styles;
49     lexbor_array_t      *stylesheets;
50     lexbor_dobject_t    *weak;
51 
52     lexbor_hash_t       *customs;
53     uintptr_t           customs_id;
54 }
55 lxb_html_document_css_t;
56 
57 struct lxb_html_document {
58     lxb_dom_document_t              dom_document;
59 
60     void                            *iframe_srcdoc;
61 
62     lxb_html_head_element_t         *head;
63     lxb_html_body_element_t         *body;
64 
65     lxb_html_document_css_t         css;
66     bool                            css_init;
67 
68     lxb_html_document_done_cb_f     done;
69     lxb_html_document_ready_state_t ready_state;
70 
71     lxb_html_document_opt_t         opt;
72 };
73 
74 
75 LXB_API lxb_html_document_t *
76 lxb_html_document_interface_create(lxb_html_document_t *document);
77 
78 LXB_API lxb_html_document_t *
79 lxb_html_document_interface_destroy(lxb_html_document_t *document);
80 
81 
82 LXB_API lxb_html_document_t *
83 lxb_html_document_create(void);
84 
85 LXB_API void
86 lxb_html_document_clean(lxb_html_document_t *document);
87 
88 LXB_API lxb_html_document_t *
89 lxb_html_document_destroy(lxb_html_document_t *document);
90 
91 LXB_API lxb_status_t
92 lxb_html_document_css_init(lxb_html_document_t *document);
93 
94 LXB_API void
95 lxb_html_document_css_destroy(lxb_html_document_t *document);
96 
97 LXB_API void
98 lxb_html_document_css_clean(lxb_html_document_t *document);
99 
100 LXB_API void
101 lxb_html_document_css_parser_attach(lxb_html_document_t *document,
102                                     lxb_css_parser_t *parser);
103 
104 LXB_API void
105 lxb_html_document_css_memory_attach(lxb_html_document_t *document,
106                                     lxb_css_memory_t *memory);
107 
108 LXB_API uintptr_t
109 lxb_html_document_css_customs_find_id(lxb_html_document_t *document,
110                                       const lxb_char_t *key, size_t length);
111 
112 LXB_API uintptr_t
113 lxb_html_document_css_customs_id(lxb_html_document_t *document,
114                                  const lxb_char_t *key, size_t length);
115 
116 LXB_API lxb_status_t
117 lxb_html_document_stylesheet_attach(lxb_html_document_t *document,
118                                     lxb_css_stylesheet_t *sst);
119 
120 LXB_API lxb_status_t
121 lxb_html_document_stylesheet_apply(lxb_html_document_t *document,
122                                    lxb_css_stylesheet_t *sst);
123 
124 LXB_API lxb_status_t
125 lxb_html_document_stylesheet_add(lxb_html_document_t *document,
126                                  lxb_css_stylesheet_t *sst);
127 
128 LXB_API lxb_status_t
129 lxb_html_document_stylesheet_remove(lxb_html_document_t *document,
130                                     lxb_css_stylesheet_t *sst);
131 
132 LXB_API lxb_status_t
133 lxb_html_document_element_styles_attach(lxb_html_element_t *element);
134 
135 LXB_API void
136 lxb_html_document_stylesheet_destroy_all(lxb_html_document_t *document,
137                                          bool destroy_memory);
138 
139 LXB_API lxb_status_t
140 lxb_html_document_style_attach(lxb_html_document_t *document,
141                                lxb_css_rule_style_t *style);
142 
143 LXB_API lxb_status_t
144 lxb_html_document_style_remove(lxb_html_document_t *document,
145                                lxb_css_rule_style_t *style);
146 
147 LXB_API lxb_status_t
148 lxb_html_document_style_attach_by_element(lxb_html_document_t *document,
149                                           lxb_html_element_t *element,
150                                           lxb_css_rule_style_t *style);
151 
152 LXB_API lxb_status_t
153 lxb_html_document_css_customs_init(lxb_html_document_t *document);
154 
155 LXB_API void
156 lxb_html_document_css_customs_destroy(lxb_html_document_t *document);
157 
158 LXB_API lxb_status_t
159 lxb_html_document_parse(lxb_html_document_t *document,
160                         const lxb_char_t *html, size_t size);
161 
162 LXB_API lxb_status_t
163 lxb_html_document_parse_chunk_begin(lxb_html_document_t *document);
164 
165 LXB_API lxb_status_t
166 lxb_html_document_parse_chunk(lxb_html_document_t *document,
167                               const lxb_char_t *html, size_t size);
168 
169 LXB_API lxb_status_t
170 lxb_html_document_parse_chunk_end(lxb_html_document_t *document);
171 
172 LXB_API lxb_dom_node_t *
173 lxb_html_document_parse_fragment(lxb_html_document_t *document,
174                                  lxb_dom_element_t *element,
175                                  const lxb_char_t *html, size_t size);
176 
177 LXB_API lxb_status_t
178 lxb_html_document_parse_fragment_chunk_begin(lxb_html_document_t *document,
179                                              lxb_dom_element_t *element);
180 
181 LXB_API lxb_status_t
182 lxb_html_document_parse_fragment_chunk(lxb_html_document_t *document,
183                                        const lxb_char_t *html, size_t size);
184 
185 LXB_API lxb_dom_node_t *
186 lxb_html_document_parse_fragment_chunk_end(lxb_html_document_t *document);
187 
188 LXB_API const lxb_char_t *
189 lxb_html_document_title(lxb_html_document_t *document, size_t *len);
190 
191 LXB_API lxb_status_t
192 lxb_html_document_title_set(lxb_html_document_t *document,
193                             const lxb_char_t *title, size_t len);
194 
195 LXB_API const lxb_char_t *
196 lxb_html_document_title_raw(lxb_html_document_t *document, size_t *len);
197 
198 LXB_API lxb_dom_node_t *
199 lxb_html_document_import_node(lxb_html_document_t *doc, lxb_dom_node_t *node,
200                               bool deep);
201 
202 /*
203  * Inline functions
204  */
205 lxb_inline lxb_html_head_element_t *
lxb_html_document_head_element(lxb_html_document_t * document)206 lxb_html_document_head_element(lxb_html_document_t *document)
207 {
208     return document->head;
209 }
210 
211 lxb_inline lxb_html_body_element_t *
lxb_html_document_body_element(lxb_html_document_t * document)212 lxb_html_document_body_element(lxb_html_document_t *document)
213 {
214     return document->body;
215 }
216 
217 lxb_inline lxb_dom_document_t *
lxb_html_document_original_ref(lxb_html_document_t * document)218 lxb_html_document_original_ref(lxb_html_document_t *document)
219 {
220     if (lxb_dom_interface_node(document)->owner_document
221         != &document->dom_document)
222     {
223         return lxb_dom_interface_node(document)->owner_document;
224     }
225 
226     return lxb_dom_interface_document(document);
227 }
228 
229 lxb_inline bool
lxb_html_document_is_original(lxb_html_document_t * document)230 lxb_html_document_is_original(lxb_html_document_t *document)
231 {
232     return lxb_dom_interface_node(document)->owner_document
233         == &document->dom_document;
234 }
235 
236 lxb_inline lexbor_mraw_t *
lxb_html_document_mraw(lxb_html_document_t * document)237 lxb_html_document_mraw(lxb_html_document_t *document)
238 {
239     return (lexbor_mraw_t *) lxb_dom_interface_document(document)->mraw;
240 }
241 
242 lxb_inline lexbor_mraw_t *
lxb_html_document_mraw_text(lxb_html_document_t * document)243 lxb_html_document_mraw_text(lxb_html_document_t *document)
244 {
245     return (lexbor_mraw_t *) lxb_dom_interface_document(document)->text;
246 }
247 
248 lxb_inline void
lxb_html_document_opt_set(lxb_html_document_t * document,lxb_html_document_opt_t opt)249 lxb_html_document_opt_set(lxb_html_document_t *document,
250                           lxb_html_document_opt_t opt)
251 {
252     document->opt = opt;
253 }
254 
255 lxb_inline lxb_html_document_opt_t
lxb_html_document_opt(lxb_html_document_t * document)256 lxb_html_document_opt(lxb_html_document_t *document)
257 {
258     return document->opt;
259 }
260 
261 lxb_inline lexbor_hash_t *
lxb_html_document_tags(lxb_html_document_t * document)262 lxb_html_document_tags(lxb_html_document_t *document)
263 {
264     return document->dom_document.tags;
265 }
266 
267 lxb_inline void *
lxb_html_document_create_struct(lxb_html_document_t * document,size_t struct_size)268 lxb_html_document_create_struct(lxb_html_document_t *document,
269                                 size_t struct_size)
270 {
271     return lexbor_mraw_calloc(lxb_dom_interface_document(document)->mraw,
272                               struct_size);
273 }
274 
275 lxb_inline void *
lxb_html_document_destroy_struct(lxb_html_document_t * document,void * data)276 lxb_html_document_destroy_struct(lxb_html_document_t *document, void *data)
277 {
278     return lexbor_mraw_free(lxb_dom_interface_document(document)->mraw, data);
279 }
280 
281 lxb_inline lxb_html_element_t *
lxb_html_document_create_element(lxb_html_document_t * document,const lxb_char_t * local_name,size_t lname_len,void * reserved_for_opt)282 lxb_html_document_create_element(lxb_html_document_t *document,
283                                  const lxb_char_t *local_name, size_t lname_len,
284                                  void *reserved_for_opt)
285 {
286     return (lxb_html_element_t *) lxb_dom_document_create_element(&document->dom_document,
287                                                                   local_name, lname_len,
288                                                                   reserved_for_opt);
289 }
290 
291 lxb_inline lxb_dom_element_t *
lxb_html_document_destroy_element(lxb_dom_element_t * element)292 lxb_html_document_destroy_element(lxb_dom_element_t *element)
293 {
294     return lxb_dom_document_destroy_element(element);
295 }
296 
297 /*
298  * No inline functions for ABI.
299  */
300 LXB_API lxb_html_head_element_t *
301 lxb_html_document_head_element_noi(lxb_html_document_t *document);
302 
303 LXB_API lxb_html_body_element_t *
304 lxb_html_document_body_element_noi(lxb_html_document_t *document);
305 
306 LXB_API lxb_dom_document_t *
307 lxb_html_document_original_ref_noi(lxb_html_document_t *document);
308 
309 LXB_API bool
310 lxb_html_document_is_original_noi(lxb_html_document_t *document);
311 
312 LXB_API lexbor_mraw_t *
313 lxb_html_document_mraw_noi(lxb_html_document_t *document);
314 
315 LXB_API lexbor_mraw_t *
316 lxb_html_document_mraw_text_noi(lxb_html_document_t *document);
317 
318 LXB_API void
319 lxb_html_document_opt_set_noi(lxb_html_document_t *document,
320                               lxb_html_document_opt_t opt);
321 
322 LXB_API lxb_html_document_opt_t
323 lxb_html_document_opt_noi(lxb_html_document_t *document);
324 
325 LXB_API void *
326 lxb_html_document_create_struct_noi(lxb_html_document_t *document,
327                                     size_t struct_size);
328 
329 LXB_API void *
330 lxb_html_document_destroy_struct_noi(lxb_html_document_t *document, void *data);
331 
332 LXB_API lxb_html_element_t *
333 lxb_html_document_create_element_noi(lxb_html_document_t *document,
334                                      const lxb_char_t *local_name,
335                                      size_t lname_len, void *reserved_for_opt);
336 
337 LXB_API lxb_dom_element_t *
338 lxb_html_document_destroy_element_noi(lxb_dom_element_t *element);
339 
340 
341 #ifdef __cplusplus
342 } /* extern "C" */
343 #endif
344 
345 #endif /* LEXBOR_HTML_DOCUMENT_H */
346