1 /*
2  * Copyright (C) 2018-2020 Alexander Borisov
3  *
4  * Author: Alexander Borisov <borisov@lexbor.com>
5  */
6 
7 #include "lexbor/html/tree/insertion_mode.h"
8 #include "lexbor/html/tree/open_elements.h"
9 
10 
11 bool
lxb_html_tree_insertion_mode_in_frameset(lxb_html_tree_t * tree,lxb_html_token_t * token)12 lxb_html_tree_insertion_mode_in_frameset(lxb_html_tree_t *tree,
13                                          lxb_html_token_t *token)
14 {
15     if (token->type & LXB_HTML_TOKEN_TYPE_CLOSE) {
16         if (token->tag_id == LXB_TAG_FRAMESET)
17         {
18             lxb_dom_node_t *node;
19             node = lxb_html_tree_current_node(tree);
20 
21             if (node == lxb_html_tree_open_elements_first(tree)) {
22                 lxb_html_tree_parse_error(tree, token,
23                                           LXB_HTML_RULES_ERROR_UNELINOPELST);
24                 return true;
25             }
26 
27             lxb_html_tree_open_elements_pop(tree);
28 
29             node = lxb_html_tree_current_node(tree);
30 
31             if (tree->fragment == NULL
32                 && lxb_html_tree_node_is(node, LXB_TAG_FRAMESET) == false)
33             {
34                 tree->mode = lxb_html_tree_insertion_mode_after_frameset;
35             }
36 
37             return true;
38         }
39 
40         lxb_html_tree_parse_error(tree, token, LXB_HTML_RULES_ERROR_UNTO);
41 
42         return true;
43     }
44 
45     switch (token->tag_id) {
46         case LXB_TAG__EM_COMMENT: {
47             lxb_dom_comment_t *comment;
48 
49             comment = lxb_html_tree_insert_comment(tree, token, NULL);
50             if (comment == NULL) {
51                 return lxb_html_tree_process_abort(tree);
52             }
53 
54             break;
55         }
56 
57         case LXB_TAG__EM_DOCTYPE:
58             lxb_html_tree_parse_error(tree, token,
59                                       LXB_HTML_RULES_ERROR_DOTOINFRMO);
60             break;
61 
62         case LXB_TAG_HTML:
63             return lxb_html_tree_insertion_mode_in_body(tree, token);
64 
65         case LXB_TAG_FRAMESET: {
66             lxb_html_element_t *element;
67 
68             element = lxb_html_tree_insert_html_element(tree, token);
69             if (element == NULL) {
70                 tree->status = LXB_STATUS_ERROR_MEMORY_ALLOCATION;
71 
72                 return lxb_html_tree_process_abort(tree);
73             }
74 
75             break;
76         }
77 
78         case LXB_TAG_FRAME: {
79             lxb_html_element_t *element;
80 
81             element = lxb_html_tree_insert_html_element(tree, token);
82             if (element == NULL) {
83                 tree->status = LXB_STATUS_ERROR_MEMORY_ALLOCATION;
84 
85                 return lxb_html_tree_process_abort(tree);
86             }
87 
88             lxb_html_tree_open_elements_pop(tree);
89             lxb_html_tree_acknowledge_token_self_closing(tree, token);
90 
91             break;
92         }
93 
94         case LXB_TAG_NOFRAMES:
95             return lxb_html_tree_insertion_mode_in_head(tree, token);
96 
97         case LXB_TAG__END_OF_FILE: {
98             lxb_dom_node_t *node = lxb_html_tree_current_node(tree);
99 
100             if (node != lxb_html_tree_open_elements_first(tree)) {
101                 lxb_html_tree_parse_error(tree, token,
102                                           LXB_HTML_RULES_ERROR_UNELINOPELST);
103             }
104 
105             tree->status = lxb_html_tree_stop_parsing(tree);
106             if (tree->status != LXB_STATUS_OK) {
107                 return lxb_html_tree_process_abort(tree);
108             }
109 
110             break;
111         }
112 
113         case LXB_TAG__TEXT: {
114             size_t cur_len;
115             lexbor_str_t str;
116 
117             tree->status = lxb_html_token_make_text(token, &str,
118                                                     tree->document->dom_document.text);
119             if (tree->status != LXB_STATUS_OK) {
120                 return lxb_html_tree_process_abort(tree);
121             }
122 
123             cur_len = str.length;
124 
125             lexbor_str_stay_only_whitespace(&str);
126 
127             if (str.length != 0) {
128                 tree->status = lxb_html_tree_insert_character_for_data(tree,
129                                                                        &str,
130                                                                        NULL);
131                 if (tree->status != LXB_STATUS_OK) {
132                     return lxb_html_tree_process_abort(tree);
133                 }
134             }
135 
136             if (str.length == cur_len) {
137                 return true;
138             }
139         }
140         /* fall through */
141 
142         default:
143             lxb_html_tree_parse_error(tree, token, LXB_HTML_RULES_ERROR_UNTO);
144 
145             break;
146     }
147 
148     return true;
149 }
150