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