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