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 #include "lexbor/html/tree/template_insertion.h"
11 
12 
13 /*
14  * "caption", "colgroup", "tbody", "tfoot", "thead"
15  */
16 lxb_inline bool
lxb_html_tree_insertion_mode_in_template_ct(lxb_html_tree_t * tree,lxb_html_token_t * token)17 lxb_html_tree_insertion_mode_in_template_ct(lxb_html_tree_t *tree,
18                                             lxb_html_token_t *token)
19 {
20     lxb_html_tree_template_insertion_pop(tree);
21 
22     tree->status = lxb_html_tree_template_insertion_push(tree,
23                                                          lxb_html_tree_insertion_mode_in_table);
24     if (tree->status != LXB_STATUS_OK) {
25         return lxb_html_tree_process_abort(tree);
26     }
27 
28     tree->mode = lxb_html_tree_insertion_mode_in_table;
29 
30     return false;
31 }
32 
33 lxb_inline bool
lxb_html_tree_insertion_mode_in_template_col(lxb_html_tree_t * tree,lxb_html_token_t * token)34 lxb_html_tree_insertion_mode_in_template_col(lxb_html_tree_t *tree,
35                                              lxb_html_token_t *token)
36 {
37     lxb_html_tree_template_insertion_pop(tree);
38 
39     tree->status = lxb_html_tree_template_insertion_push(tree,
40                                                          lxb_html_tree_insertion_mode_in_column_group);
41     if (tree->status != LXB_STATUS_OK) {
42         return lxb_html_tree_process_abort(tree);
43     }
44 
45     tree->mode = lxb_html_tree_insertion_mode_in_column_group;
46 
47     return false;
48 }
49 
50 lxb_inline bool
lxb_html_tree_insertion_mode_in_template_tr(lxb_html_tree_t * tree,lxb_html_token_t * token)51 lxb_html_tree_insertion_mode_in_template_tr(lxb_html_tree_t *tree,
52                                             lxb_html_token_t *token)
53 {
54     lxb_html_tree_template_insertion_pop(tree);
55 
56     tree->status = lxb_html_tree_template_insertion_push(tree,
57                                                          lxb_html_tree_insertion_mode_in_table_body);
58     if (tree->status != LXB_STATUS_OK) {
59         return lxb_html_tree_process_abort(tree);
60     }
61 
62     tree->mode = lxb_html_tree_insertion_mode_in_table_body;
63 
64     return false;
65 }
66 
67 /*
68  * "td", "th"
69  */
70 lxb_inline bool
lxb_html_tree_insertion_mode_in_template_tdth(lxb_html_tree_t * tree,lxb_html_token_t * token)71 lxb_html_tree_insertion_mode_in_template_tdth(lxb_html_tree_t *tree,
72                                               lxb_html_token_t *token)
73 {
74     lxb_html_tree_template_insertion_pop(tree);
75 
76     tree->status = lxb_html_tree_template_insertion_push(tree,
77                                                          lxb_html_tree_insertion_mode_in_row);
78     if (tree->status != LXB_STATUS_OK) {
79         return lxb_html_tree_process_abort(tree);
80     }
81 
82     tree->mode = lxb_html_tree_insertion_mode_in_row;
83 
84     return false;
85 }
86 
87 lxb_inline bool
lxb_html_tree_insertion_mode_in_template_end_of_file(lxb_html_tree_t * tree,lxb_html_token_t * token)88 lxb_html_tree_insertion_mode_in_template_end_of_file(lxb_html_tree_t *tree,
89                                                      lxb_html_token_t *token)
90 {
91     lxb_dom_node_t *node;
92 
93     node = lxb_html_tree_open_elements_find(tree, LXB_TAG_TEMPLATE, LXB_NS_HTML,
94                                             NULL);
95     if (node == NULL) {
96         tree->status =  lxb_html_tree_stop_parsing(tree);
97         if (tree->status != LXB_STATUS_OK) {
98             return lxb_html_tree_process_abort(tree);
99         }
100 
101         return true;
102     }
103 
104     lxb_html_tree_parse_error(tree, token, LXB_HTML_RULES_ERROR_UNENOFFI);
105 
106     lxb_html_tree_open_elements_pop_until_tag_id(tree, LXB_TAG_TEMPLATE,
107                                                  LXB_NS_HTML, true);
108 
109     lxb_html_tree_active_formatting_up_to_last_marker(tree);
110     lxb_html_tree_template_insertion_pop(tree);
111     lxb_html_tree_reset_insertion_mode_appropriately(tree);
112 
113     return false;
114 }
115 
116 lxb_inline bool
lxb_html_tree_insertion_mode_in_template_anything_else(lxb_html_tree_t * tree,lxb_html_token_t * token)117 lxb_html_tree_insertion_mode_in_template_anything_else(lxb_html_tree_t *tree,
118                                                        lxb_html_token_t *token)
119 {
120     lxb_html_tree_template_insertion_pop(tree);
121 
122     tree->status = lxb_html_tree_template_insertion_push(tree,
123                                                          lxb_html_tree_insertion_mode_in_body);
124     if (tree->status != LXB_STATUS_OK) {
125         return lxb_html_tree_process_abort(tree);
126     }
127 
128     tree->mode = lxb_html_tree_insertion_mode_in_body;
129 
130     return false;
131 }
132 
133 bool
lxb_html_tree_insertion_mode_in_template(lxb_html_tree_t * tree,lxb_html_token_t * token)134 lxb_html_tree_insertion_mode_in_template(lxb_html_tree_t *tree,
135                                          lxb_html_token_t *token)
136 {
137     if (token->type & LXB_HTML_TOKEN_TYPE_CLOSE) {
138         if (token->tag_id == LXB_TAG_TEMPLATE) {
139             return lxb_html_tree_insertion_mode_in_head(tree, token);
140         }
141 
142         lxb_html_tree_parse_error(tree, token, LXB_HTML_RULES_ERROR_UNCLTO);
143 
144         return true;
145     }
146 
147     switch (token->tag_id) {
148         case LXB_TAG__TEXT:
149         case LXB_TAG__EM_COMMENT:
150         case LXB_TAG__EM_DOCTYPE:
151             return lxb_html_tree_insertion_mode_in_body(tree, token);
152 
153         case LXB_TAG_BASE:
154         case LXB_TAG_BASEFONT:
155         case LXB_TAG_BGSOUND:
156         case LXB_TAG_LINK:
157         case LXB_TAG_META:
158         case LXB_TAG_NOFRAMES:
159         case LXB_TAG_SCRIPT:
160         case LXB_TAG_STYLE:
161         case LXB_TAG_TEMPLATE:
162         case LXB_TAG_TITLE:
163             return lxb_html_tree_insertion_mode_in_head(tree, token);
164 
165         case LXB_TAG_CAPTION:
166         case LXB_TAG_COLGROUP:
167         case LXB_TAG_TBODY:
168         case LXB_TAG_TFOOT:
169         case LXB_TAG_THEAD:
170             return lxb_html_tree_insertion_mode_in_template_ct(tree, token);
171 
172         case LXB_TAG_COL:
173             return lxb_html_tree_insertion_mode_in_template_col(tree, token);
174 
175         case LXB_TAG_TR:
176             return lxb_html_tree_insertion_mode_in_template_tr(tree, token);
177 
178         case LXB_TAG_TD:
179         case LXB_TAG_TH:
180             return lxb_html_tree_insertion_mode_in_template_tdth(tree, token);
181 
182         case LXB_TAG__END_OF_FILE:
183             return lxb_html_tree_insertion_mode_in_template_end_of_file(tree,
184                                                                         token);
185         default:
186             return lxb_html_tree_insertion_mode_in_template_anything_else(tree,
187                                                                           token);
188     }
189 }
190