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