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_close_cell(lxb_html_tree_t * tree,lxb_html_token_t * token)13 lxb_html_tree_close_cell(lxb_html_tree_t *tree, lxb_html_token_t *token)
14 {
15 lxb_dom_node_t *node;
16
17 lxb_html_tree_generate_implied_end_tags(tree, LXB_TAG__UNDEF,
18 LXB_NS__UNDEF);
19
20 node = lxb_html_tree_current_node(tree);
21
22 if (lxb_html_tree_node_is(node, LXB_TAG_TD) == false
23 && lxb_html_tree_node_is(node, LXB_TAG_TH) == false)
24 {
25 lxb_html_tree_parse_error(tree, token,
26 LXB_HTML_RULES_ERROR_MIELINOPELST);
27 }
28
29 lxb_html_tree_open_elements_pop_until_td_th(tree);
30 lxb_html_tree_active_formatting_up_to_last_marker(tree);
31
32 tree->mode = lxb_html_tree_insertion_mode_in_row;
33 }
34
35 /*
36 * "td", "th"
37 */
38 lxb_inline bool
lxb_html_tree_insertion_mode_in_cell_tdth_closed(lxb_html_tree_t * tree,lxb_html_token_t * token)39 lxb_html_tree_insertion_mode_in_cell_tdth_closed(lxb_html_tree_t *tree,
40 lxb_html_token_t *token)
41 {
42 lxb_dom_node_t *node;
43
44 node = lxb_html_tree_element_in_scope(tree, token->tag_id, LXB_NS_HTML,
45 LXB_HTML_TAG_CATEGORY_SCOPE_TABLE);
46 if (node == NULL) {
47 lxb_html_tree_parse_error(tree, token, LXB_HTML_RULES_ERROR_UNCLTO);
48
49 return true;
50 }
51
52 lxb_html_tree_generate_implied_end_tags(tree, LXB_TAG__UNDEF,
53 LXB_NS__UNDEF);
54
55 node = lxb_html_tree_current_node(tree);
56
57 if (lxb_html_tree_node_is(node, token->tag_id) == false) {
58 lxb_html_tree_parse_error(tree, token,
59 LXB_HTML_RULES_ERROR_MIELINOPELST);
60 }
61
62 lxb_html_tree_open_elements_pop_until_tag_id(tree, token->tag_id,
63 LXB_NS_HTML, true);
64
65 lxb_html_tree_active_formatting_up_to_last_marker(tree);
66
67 tree->mode = lxb_html_tree_insertion_mode_in_row;
68
69 return true;
70 }
71
72 /*
73 * "caption", "col", "colgroup", "tbody", "td", "tfoot", "th", "thead", "tr"
74 */
75 lxb_inline bool
lxb_html_tree_insertion_mode_in_cell_ct(lxb_html_tree_t * tree,lxb_html_token_t * token)76 lxb_html_tree_insertion_mode_in_cell_ct(lxb_html_tree_t *tree,
77 lxb_html_token_t *token)
78 {
79 lxb_dom_node_t *node;
80
81 node = lxb_html_tree_element_in_scope_td_th(tree);
82 if (node == NULL) {
83 lxb_html_tree_parse_error(tree, token, LXB_HTML_RULES_ERROR_MIELINSC);
84
85 return true;
86 }
87
88 lxb_html_tree_close_cell(tree, token);
89
90 return false;
91 }
92
93 /*
94 * "body", "caption", "col", "colgroup", "html"
95 */
96 lxb_inline bool
lxb_html_tree_insertion_mode_in_cell_bch_closed(lxb_html_tree_t * tree,lxb_html_token_t * token)97 lxb_html_tree_insertion_mode_in_cell_bch_closed(lxb_html_tree_t *tree,
98 lxb_html_token_t *token)
99 {
100 lxb_html_tree_parse_error(tree, token, LXB_HTML_RULES_ERROR_UNCLTO);
101
102 return true;
103 }
104
105 /*
106 * "table", "tbody", "tfoot", "thead", "tr"
107 */
108 lxb_inline bool
lxb_html_tree_insertion_mode_in_cell_t_closed(lxb_html_tree_t * tree,lxb_html_token_t * token)109 lxb_html_tree_insertion_mode_in_cell_t_closed(lxb_html_tree_t *tree,
110 lxb_html_token_t *token)
111 {
112 lxb_dom_node_t *node;
113
114 node = lxb_html_tree_element_in_scope(tree, token->tag_id, LXB_NS_HTML,
115 LXB_HTML_TAG_CATEGORY_SCOPE_TABLE);
116 if (node == NULL) {
117 lxb_html_tree_parse_error(tree, token, LXB_HTML_RULES_ERROR_UNCLTO);
118
119 return true;
120 }
121
122 lxb_html_tree_close_cell(tree, token);
123
124 return false;
125 }
126
127 lxb_inline bool
lxb_html_tree_insertion_mode_in_cell_anything_else(lxb_html_tree_t * tree,lxb_html_token_t * token)128 lxb_html_tree_insertion_mode_in_cell_anything_else(lxb_html_tree_t *tree,
129 lxb_html_token_t *token)
130 {
131 return lxb_html_tree_insertion_mode_in_body(tree, token);
132 }
133
134 lxb_inline bool
lxb_html_tree_insertion_mode_in_cell_anything_else_closed(lxb_html_tree_t * tree,lxb_html_token_t * token)135 lxb_html_tree_insertion_mode_in_cell_anything_else_closed(lxb_html_tree_t *tree,
136 lxb_html_token_t *token)
137 {
138 return lxb_html_tree_insertion_mode_in_cell_anything_else(tree, token);
139 }
140
141 bool
lxb_html_tree_insertion_mode_in_cell(lxb_html_tree_t * tree,lxb_html_token_t * token)142 lxb_html_tree_insertion_mode_in_cell(lxb_html_tree_t *tree,
143 lxb_html_token_t *token)
144 {
145 if (token->type & LXB_HTML_TOKEN_TYPE_CLOSE) {
146 switch (token->tag_id) {
147 case LXB_TAG_TD:
148 case LXB_TAG_TH:
149 return lxb_html_tree_insertion_mode_in_cell_tdth_closed(tree,
150 token);
151 case LXB_TAG_BODY:
152 case LXB_TAG_CAPTION:
153 case LXB_TAG_COL:
154 case LXB_TAG_COLGROUP:
155 case LXB_TAG_HTML:
156 return lxb_html_tree_insertion_mode_in_cell_bch_closed(tree,
157 token);
158 case LXB_TAG_TABLE:
159 case LXB_TAG_TBODY:
160 case LXB_TAG_TFOOT:
161 case LXB_TAG_THEAD:
162 case LXB_TAG_TR:
163 return lxb_html_tree_insertion_mode_in_cell_t_closed(tree,
164 token);
165 default:
166 return lxb_html_tree_insertion_mode_in_cell_anything_else_closed(tree,
167 token);
168 }
169 }
170
171 switch (token->tag_id) {
172 case LXB_TAG_CAPTION:
173 case LXB_TAG_COL:
174 case LXB_TAG_COLGROUP:
175 case LXB_TAG_TBODY:
176 case LXB_TAG_TD:
177 case LXB_TAG_TFOOT:
178 case LXB_TAG_TH:
179 case LXB_TAG_THEAD:
180 case LXB_TAG_TR:
181 return lxb_html_tree_insertion_mode_in_cell_ct(tree, token);
182
183 default:
184 return lxb_html_tree_insertion_mode_in_cell_anything_else(tree,
185 token);
186 }
187 }
188