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 lxb_inline bool
lxb_html_tree_insertion_mode_in_select_text(lxb_html_tree_t * tree,lxb_html_token_t * token)12 lxb_html_tree_insertion_mode_in_select_text(lxb_html_tree_t *tree,
13 lxb_html_token_t *token)
14 {
15 lexbor_str_t str;
16
17 if (token->null_count != 0) {
18 lxb_html_tree_parse_error(tree, token,
19 LXB_HTML_RULES_ERROR_NUCH);
20
21 tree->status = lxb_html_token_make_text_drop_null(token, &str,
22 tree->document->dom_document.text);
23 }
24 else {
25 tree->status = lxb_html_token_make_text(token, &str,
26 tree->document->dom_document.text);
27 }
28
29 if (tree->status != LXB_STATUS_OK) {
30 return lxb_html_tree_process_abort(tree);
31 }
32
33 /* Can be zero only if all NULL are gone */
34 if (str.length == 0) {
35 lexbor_str_destroy(&str, tree->document->dom_document.text, false);
36
37 return true;
38 }
39
40 tree->status = lxb_html_tree_insert_character_for_data(tree, &str, NULL);
41 if (tree->status != LXB_STATUS_OK) {
42 return lxb_html_tree_process_abort(tree);
43 }
44
45 return true;
46 }
47
48 lxb_inline bool
lxb_html_tree_insertion_mode_in_select_comment(lxb_html_tree_t * tree,lxb_html_token_t * token)49 lxb_html_tree_insertion_mode_in_select_comment(lxb_html_tree_t *tree,
50 lxb_html_token_t *token)
51 {
52 lxb_dom_comment_t *comment;
53
54 comment = lxb_html_tree_insert_comment(tree, token, NULL);
55 if (comment == NULL) {
56 tree->status = LXB_STATUS_ERROR_MEMORY_ALLOCATION;
57
58 return lxb_html_tree_process_abort(tree);
59 }
60
61 return true;
62 }
63
64 lxb_inline bool
lxb_html_tree_insertion_mode_in_select_doctype(lxb_html_tree_t * tree,lxb_html_token_t * token)65 lxb_html_tree_insertion_mode_in_select_doctype(lxb_html_tree_t *tree,
66 lxb_html_token_t *token)
67 {
68 lxb_html_tree_parse_error(tree, token, LXB_HTML_RULES_ERROR_DOTOINSEMO);
69
70 return true;
71 }
72
73 lxb_inline bool
lxb_html_tree_insertion_mode_in_select_html(lxb_html_tree_t * tree,lxb_html_token_t * token)74 lxb_html_tree_insertion_mode_in_select_html(lxb_html_tree_t *tree,
75 lxb_html_token_t *token)
76 {
77 return lxb_html_tree_insertion_mode_in_body(tree, token);
78 }
79
80 lxb_inline bool
lxb_html_tree_insertion_mode_in_select_option(lxb_html_tree_t * tree,lxb_html_token_t * token)81 lxb_html_tree_insertion_mode_in_select_option(lxb_html_tree_t *tree,
82 lxb_html_token_t *token)
83 {
84 lxb_html_element_t *element;
85 lxb_dom_node_t *node = lxb_html_tree_current_node(tree);
86
87 if (lxb_html_tree_node_is(node, LXB_TAG_OPTION)) {
88 lxb_html_tree_open_elements_pop(tree);
89 }
90
91 element = lxb_html_tree_insert_html_element(tree, token);
92 if (element == NULL) {
93 tree->status = LXB_STATUS_ERROR_MEMORY_ALLOCATION;
94
95 return lxb_html_tree_process_abort(tree);
96 }
97
98 return true;
99 }
100
101 lxb_inline bool
lxb_html_tree_insertion_mode_in_select_optgroup(lxb_html_tree_t * tree,lxb_html_token_t * token)102 lxb_html_tree_insertion_mode_in_select_optgroup(lxb_html_tree_t *tree,
103 lxb_html_token_t *token)
104 {
105 lxb_html_element_t *element;
106 lxb_dom_node_t *node = lxb_html_tree_current_node(tree);
107
108 if (lxb_html_tree_node_is(node, LXB_TAG_OPTION)) {
109 lxb_html_tree_open_elements_pop(tree);
110 }
111
112 node = lxb_html_tree_current_node(tree);
113
114 if (lxb_html_tree_node_is(node, LXB_TAG_OPTGROUP)) {
115 lxb_html_tree_open_elements_pop(tree);
116 }
117
118 element = lxb_html_tree_insert_html_element(tree, token);
119 if (element == NULL) {
120 tree->status = LXB_STATUS_ERROR_MEMORY_ALLOCATION;
121
122 return lxb_html_tree_process_abort(tree);
123 }
124
125 return true;
126 }
127
128 lxb_inline bool
lxb_html_tree_insertion_mode_in_select_optgroup_closed(lxb_html_tree_t * tree,lxb_html_token_t * token)129 lxb_html_tree_insertion_mode_in_select_optgroup_closed(lxb_html_tree_t *tree,
130 lxb_html_token_t *token)
131 {
132 lxb_dom_node_t *node = lxb_html_tree_current_node(tree);
133
134 if (lxb_html_tree_node_is(node, LXB_TAG_OPTION)
135 && tree->open_elements->length > 1)
136 {
137 node = lxb_html_tree_open_elements_get(tree,
138 tree->open_elements->length - 2);
139 if (node != NULL && lxb_html_tree_node_is(node, LXB_TAG_OPTGROUP)) {
140 lxb_html_tree_open_elements_pop(tree);
141 }
142 }
143
144 node = lxb_html_tree_current_node(tree);
145
146 if (lxb_html_tree_node_is(node, LXB_TAG_OPTGROUP) == false) {
147 lxb_html_tree_parse_error(tree, token,
148 LXB_HTML_RULES_ERROR_UNELINOPELST);
149 return true;
150 }
151
152 lxb_html_tree_open_elements_pop(tree);
153
154 return true;
155 }
156
157 lxb_inline bool
lxb_html_tree_insertion_mode_in_select_option_closed(lxb_html_tree_t * tree,lxb_html_token_t * token)158 lxb_html_tree_insertion_mode_in_select_option_closed(lxb_html_tree_t *tree,
159 lxb_html_token_t *token)
160 {
161 lxb_dom_node_t *node = lxb_html_tree_current_node(tree);
162
163 if (lxb_html_tree_node_is(node, LXB_TAG_OPTION) == false) {
164 lxb_html_tree_parse_error(tree, token,
165 LXB_HTML_RULES_ERROR_UNELINOPELST);
166 return true;
167 }
168
169 lxb_html_tree_open_elements_pop(tree);
170
171 return true;
172 }
173
174 lxb_inline bool
lxb_html_tree_insertion_mode_in_select_select_closed(lxb_html_tree_t * tree,lxb_html_token_t * token)175 lxb_html_tree_insertion_mode_in_select_select_closed(lxb_html_tree_t *tree,
176 lxb_html_token_t *token)
177 {
178 lxb_dom_node_t *node;
179
180 node = lxb_html_tree_element_in_scope(tree, LXB_TAG_SELECT, LXB_NS_HTML,
181 LXB_HTML_TAG_CATEGORY_SCOPE_SELECT);
182 if (node == NULL) {
183 lxb_html_tree_parse_error(tree, token, LXB_HTML_RULES_ERROR_UNCLTO);
184
185 return true;
186 }
187
188 lxb_html_tree_open_elements_pop_until_tag_id(tree, LXB_TAG_SELECT,
189 LXB_NS_HTML, true);
190
191 lxb_html_tree_reset_insertion_mode_appropriately(tree);
192
193 return true;
194 }
195
196 lxb_inline bool
lxb_html_tree_insertion_mode_in_select_select(lxb_html_tree_t * tree,lxb_html_token_t * token)197 lxb_html_tree_insertion_mode_in_select_select(lxb_html_tree_t *tree,
198 lxb_html_token_t *token)
199 {
200 lxb_dom_node_t *node;
201
202 lxb_html_tree_parse_error(tree, token, LXB_HTML_RULES_ERROR_UNTO);
203
204 node = lxb_html_tree_element_in_scope(tree, LXB_TAG_SELECT, LXB_NS_HTML,
205 LXB_HTML_TAG_CATEGORY_SCOPE_SELECT);
206 if (node == NULL) {
207 return true;
208 }
209
210 lxb_html_tree_open_elements_pop_until_tag_id(tree, LXB_TAG_SELECT,
211 LXB_NS_HTML, true);
212
213 lxb_html_tree_reset_insertion_mode_appropriately(tree);
214
215 return true;
216 }
217
218 /*
219 * "input", "keygen", "textarea"
220 */
221 lxb_inline bool
lxb_html_tree_insertion_mode_in_select_ikt(lxb_html_tree_t * tree,lxb_html_token_t * token)222 lxb_html_tree_insertion_mode_in_select_ikt(lxb_html_tree_t *tree,
223 lxb_html_token_t *token)
224 {
225 lxb_dom_node_t *node;
226
227 lxb_html_tree_parse_error(tree, token, LXB_HTML_RULES_ERROR_UNTO);
228
229 node = lxb_html_tree_element_in_scope(tree, LXB_TAG_SELECT, LXB_NS_HTML,
230 LXB_HTML_TAG_CATEGORY_SCOPE_SELECT);
231 if (node == NULL) {
232 return true;
233 }
234
235 lxb_html_tree_open_elements_pop_until_tag_id(tree, LXB_TAG_SELECT,
236 LXB_NS_HTML, true);
237
238 lxb_html_tree_reset_insertion_mode_appropriately(tree);
239
240 return false;
241 }
242
243 /*
244 * A start tag whose tag name is one of: "script", "template"
245 * An end tag whose tag name is "template"
246 */
247 lxb_inline bool
lxb_html_tree_insertion_mode_in_select_st_open_closed(lxb_html_tree_t * tree,lxb_html_token_t * token)248 lxb_html_tree_insertion_mode_in_select_st_open_closed(lxb_html_tree_t *tree,
249 lxb_html_token_t *token)
250 {
251 return lxb_html_tree_insertion_mode_in_head(tree, token);
252 }
253
254 lxb_inline bool
lxb_html_tree_insertion_mode_in_select_end_of_file(lxb_html_tree_t * tree,lxb_html_token_t * token)255 lxb_html_tree_insertion_mode_in_select_end_of_file(lxb_html_tree_t *tree,
256 lxb_html_token_t *token)
257 {
258 return lxb_html_tree_insertion_mode_in_body(tree, token);
259 }
260
261 lxb_inline bool
lxb_html_tree_insertion_mode_in_select_anything_else(lxb_html_tree_t * tree,lxb_html_token_t * token)262 lxb_html_tree_insertion_mode_in_select_anything_else(lxb_html_tree_t *tree,
263 lxb_html_token_t *token)
264 {
265 lxb_html_tree_parse_error(tree, token, LXB_HTML_RULES_ERROR_UNTO);
266
267 return true;
268 }
269
270 lxb_inline bool
lxb_html_tree_insertion_mode_in_select_anything_else_closed(lxb_html_tree_t * tree,lxb_html_token_t * token)271 lxb_html_tree_insertion_mode_in_select_anything_else_closed(lxb_html_tree_t *tree,
272 lxb_html_token_t *token)
273 {
274 lxb_html_tree_parse_error(tree, token, LXB_HTML_RULES_ERROR_UNCLTO);
275
276 return true;
277 }
278
279 bool
lxb_html_tree_insertion_mode_in_select(lxb_html_tree_t * tree,lxb_html_token_t * token)280 lxb_html_tree_insertion_mode_in_select(lxb_html_tree_t *tree,
281 lxb_html_token_t *token)
282 {
283 if (token->type & LXB_HTML_TOKEN_TYPE_CLOSE) {
284 switch (token->tag_id) {
285 case LXB_TAG_OPTGROUP:
286 return lxb_html_tree_insertion_mode_in_select_optgroup_closed(tree,
287 token);
288 case LXB_TAG_OPTION:
289 return lxb_html_tree_insertion_mode_in_select_option_closed(tree,
290 token);
291 case LXB_TAG_SELECT:
292 return lxb_html_tree_insertion_mode_in_select_select_closed(tree,
293 token);
294 case LXB_TAG_TEMPLATE:
295 return lxb_html_tree_insertion_mode_in_select_st_open_closed(tree,
296 token);
297 default:
298 return lxb_html_tree_insertion_mode_in_select_anything_else_closed(tree,
299 token);
300 }
301 }
302
303 switch (token->tag_id) {
304 case LXB_TAG__TEXT:
305 return lxb_html_tree_insertion_mode_in_select_text(tree, token);
306
307 case LXB_TAG__EM_COMMENT:
308 return lxb_html_tree_insertion_mode_in_select_comment(tree, token);
309
310 case LXB_TAG__EM_DOCTYPE:
311 return lxb_html_tree_insertion_mode_in_select_doctype(tree, token);
312
313 case LXB_TAG_HTML:
314 return lxb_html_tree_insertion_mode_in_select_html(tree, token);
315
316 case LXB_TAG_OPTION:
317 return lxb_html_tree_insertion_mode_in_select_option(tree, token);
318
319 case LXB_TAG_OPTGROUP:
320 return lxb_html_tree_insertion_mode_in_select_optgroup(tree, token);
321
322 case LXB_TAG_SELECT:
323 return lxb_html_tree_insertion_mode_in_select_select(tree, token);
324
325 case LXB_TAG_INPUT:
326 case LXB_TAG_KEYGEN:
327 case LXB_TAG_TEXTAREA:
328 return lxb_html_tree_insertion_mode_in_select_ikt(tree, token);
329
330 case LXB_TAG_SCRIPT:
331 case LXB_TAG_TEMPLATE:
332 return lxb_html_tree_insertion_mode_in_select_st_open_closed(tree,
333 token);
334 case LXB_TAG__END_OF_FILE:
335 return lxb_html_tree_insertion_mode_in_select_end_of_file(tree,
336 token);
337 default:
338 return lxb_html_tree_insertion_mode_in_select_anything_else(tree,
339 token);
340 }
341 }
342