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