1 /*
2  * Copyright (C) 2018-2019 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 static void
lxb_html_tree_clear_stack_back_to_table_body(lxb_html_tree_t * tree)12 lxb_html_tree_clear_stack_back_to_table_body(lxb_html_tree_t *tree)
13 {
14     lxb_dom_node_t *current = lxb_html_tree_current_node(tree);
15 
16     while ((current->local_name != LXB_TAG_TBODY
17             && current->local_name != LXB_TAG_TFOOT
18             && current->local_name != LXB_TAG_THEAD
19             && current->local_name != LXB_TAG_TEMPLATE
20             && current->local_name != LXB_TAG_HTML)
21            || current->ns != LXB_NS_HTML)
22     {
23         lxb_html_tree_open_elements_pop(tree);
24         current = lxb_html_tree_current_node(tree);
25     }
26 }
27 
28 lxb_inline bool
lxb_html_tree_insertion_mode_in_table_body_tr(lxb_html_tree_t * tree,lxb_html_token_t * token)29 lxb_html_tree_insertion_mode_in_table_body_tr(lxb_html_tree_t *tree,
30                                               lxb_html_token_t *token)
31 {
32     lxb_html_element_t *element;
33 
34     lxb_html_tree_clear_stack_back_to_table_body(tree);
35 
36     element = lxb_html_tree_insert_html_element(tree, token);
37     if (element == NULL) {
38         tree->status = LXB_STATUS_ERROR_MEMORY_ALLOCATION;
39 
40         return lxb_html_tree_process_abort(tree);
41     }
42 
43     tree->mode = lxb_html_tree_insertion_mode_in_row;
44 
45     return true;
46 }
47 
48 /*
49  * "th", "td"
50  */
51 lxb_inline bool
lxb_html_tree_insertion_mode_in_table_body_thtd(lxb_html_tree_t * tree,lxb_html_token_t * token)52 lxb_html_tree_insertion_mode_in_table_body_thtd(lxb_html_tree_t *tree,
53                                                 lxb_html_token_t *token)
54 {
55     lxb_html_token_t fake_token;
56     lxb_html_element_t *element;
57 
58     lxb_html_tree_parse_error(tree, token, LXB_HTML_RULES_ERROR_UNTO);
59 
60     lxb_html_tree_clear_stack_back_to_table_body(tree);
61 
62     fake_token = *token;
63 
64     fake_token.tag_id = LXB_TAG_TR;
65     fake_token.attr_first = NULL;
66     fake_token.attr_last = NULL;
67 
68     element = lxb_html_tree_insert_html_element(tree, &fake_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     tree->mode = lxb_html_tree_insertion_mode_in_row;
76 
77     return false;
78 }
79 
80 /*
81  * "tbody", "tfoot", "thead"
82  */
83 lxb_inline bool
lxb_html_tree_insertion_mode_in_table_body_tbtfth_closed(lxb_html_tree_t * tree,lxb_html_token_t * token)84 lxb_html_tree_insertion_mode_in_table_body_tbtfth_closed(lxb_html_tree_t *tree,
85                                                          lxb_html_token_t *token)
86 {
87     lxb_dom_node_t *node;
88 
89     node = lxb_html_tree_element_in_scope(tree, token->tag_id, LXB_NS_HTML,
90                                           LXB_HTML_TAG_CATEGORY_SCOPE_TABLE);
91     if (node == NULL) {
92         lxb_html_tree_parse_error(tree, token, LXB_HTML_RULES_ERROR_MIELINSC);
93 
94         return true;
95     }
96 
97     lxb_html_tree_clear_stack_back_to_table_body(tree);
98     lxb_html_tree_open_elements_pop(tree);
99 
100     tree->mode = lxb_html_tree_insertion_mode_in_table;
101 
102     return true;
103 }
104 
105 /*
106  * A start tag whose tag name is one of: "caption", "col", "colgroup", "tbody",
107  * "tfoot", "thead"
108  * An end tag whose tag name is "table"
109  */
110 lxb_inline bool
lxb_html_tree_insertion_mode_in_table_body_ct_open_closed(lxb_html_tree_t * tree,lxb_html_token_t * token)111 lxb_html_tree_insertion_mode_in_table_body_ct_open_closed(lxb_html_tree_t *tree,
112                                                           lxb_html_token_t *token)
113 {
114     lxb_dom_node_t *node;
115 
116     node = lxb_html_tree_element_in_scope_tbody_thead_tfoot(tree);
117     if (node == NULL) {
118         lxb_html_tree_parse_error(tree, token, LXB_HTML_RULES_ERROR_MIELINSC);
119 
120         return true;
121     }
122 
123     lxb_html_tree_clear_stack_back_to_table_body(tree);
124     lxb_html_tree_open_elements_pop(tree);
125 
126     tree->mode = lxb_html_tree_insertion_mode_in_table;
127 
128     return false;
129 }
130 
131 /*
132  * "body", "caption", "col", "colgroup", "html", "td", "th", "tr"
133  */
134 lxb_inline bool
lxb_html_tree_insertion_mode_in_table_body_bcht_closed(lxb_html_tree_t * tree,lxb_html_token_t * token)135 lxb_html_tree_insertion_mode_in_table_body_bcht_closed(lxb_html_tree_t *tree,
136                                                        lxb_html_token_t *token)
137 {
138     lxb_html_tree_parse_error(tree, token, LXB_HTML_RULES_ERROR_UNCLTO);
139 
140     return true;
141 }
142 
143 lxb_inline bool
lxb_html_tree_insertion_mode_in_table_body_anything_else(lxb_html_tree_t * tree,lxb_html_token_t * token)144 lxb_html_tree_insertion_mode_in_table_body_anything_else(lxb_html_tree_t *tree,
145                                                          lxb_html_token_t *token)
146 {
147     return lxb_html_tree_insertion_mode_in_table(tree, token);
148 }
149 
150 lxb_inline bool
lxb_html_tree_insertion_mode_in_table_body_anything_else_closed(lxb_html_tree_t * tree,lxb_html_token_t * token)151 lxb_html_tree_insertion_mode_in_table_body_anything_else_closed(lxb_html_tree_t *tree,
152                                                                 lxb_html_token_t *token)
153 {
154     return lxb_html_tree_insertion_mode_in_table_body_anything_else(tree,
155                                                                     token);
156 }
157 
158 bool
lxb_html_tree_insertion_mode_in_table_body(lxb_html_tree_t * tree,lxb_html_token_t * token)159 lxb_html_tree_insertion_mode_in_table_body(lxb_html_tree_t *tree,
160                                            lxb_html_token_t *token)
161 {
162     if (token->type & LXB_HTML_TOKEN_TYPE_CLOSE) {
163         switch (token->tag_id) {
164             case LXB_TAG_TBODY:
165             case LXB_TAG_TFOOT:
166             case LXB_TAG_THEAD:
167                 return lxb_html_tree_insertion_mode_in_table_body_tbtfth_closed(tree,
168                                                                                 token);
169             case LXB_TAG_TABLE:
170                 return lxb_html_tree_insertion_mode_in_table_body_ct_open_closed(tree,
171                                                                                  token);
172             case LXB_TAG_BODY:
173             case LXB_TAG_CAPTION:
174             case LXB_TAG_COL:
175             case LXB_TAG_COLGROUP:
176             case LXB_TAG_HTML:
177             case LXB_TAG_TD:
178             case LXB_TAG_TH:
179             case LXB_TAG_TR:
180                 return lxb_html_tree_insertion_mode_in_table_body_bcht_closed(tree,
181                                                                               token);
182             default:
183                 return lxb_html_tree_insertion_mode_in_table_body_anything_else_closed(tree,
184                                                                                        token);
185         }
186     }
187 
188     switch (token->tag_id) {
189         case LXB_TAG_TR:
190             return lxb_html_tree_insertion_mode_in_table_body_tr(tree, token);
191 
192         case LXB_TAG_TH:
193         case LXB_TAG_TD:
194             return lxb_html_tree_insertion_mode_in_table_body_thtd(tree, token);
195 
196         case LXB_TAG_CAPTION:
197         case LXB_TAG_COL:
198         case LXB_TAG_COLGROUP:
199         case LXB_TAG_TBODY:
200         case LXB_TAG_TFOOT:
201         case LXB_TAG_THEAD:
202             return lxb_html_tree_insertion_mode_in_table_body_ct_open_closed(tree,
203                                                                              token);
204         default:
205             return lxb_html_tree_insertion_mode_in_table_body_anything_else(tree,
206                                                                             token);
207     }
208 }
209