1 /*
2 * Copyright (C) 2018-2020 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/interfaces/html_element.h"
10
11
12 static bool
13 lxb_html_tree_insertion_mode_before_html_open(lxb_html_tree_t *tree,
14 lxb_html_token_t *token);
15
16 static bool
17 lxb_html_tree_insertion_mode_before_html_closed(lxb_html_tree_t *tree,
18 lxb_html_token_t *token);
19
20 lxb_inline bool
21 lxb_html_tree_insertion_mode_before_html_anything_else(lxb_html_tree_t *tree);
22
23 lxb_inline lxb_status_t
24 lxb_html_tree_insertion_mode_before_html_html(lxb_html_tree_t *tree,
25 lxb_dom_node_t *node_html);
26
27
28 bool
lxb_html_tree_insertion_mode_before_html(lxb_html_tree_t * tree,lxb_html_token_t * token)29 lxb_html_tree_insertion_mode_before_html(lxb_html_tree_t *tree,
30 lxb_html_token_t *token)
31 {
32 if (token->type & LXB_HTML_TOKEN_TYPE_CLOSE) {
33 return lxb_html_tree_insertion_mode_before_html_closed(tree, token);;
34 }
35
36 return lxb_html_tree_insertion_mode_before_html_open(tree, token);
37 }
38
39 static bool
lxb_html_tree_insertion_mode_before_html_open(lxb_html_tree_t * tree,lxb_html_token_t * token)40 lxb_html_tree_insertion_mode_before_html_open(lxb_html_tree_t *tree,
41 lxb_html_token_t *token)
42 {
43 switch (token->tag_id) {
44 case LXB_TAG__EM_DOCTYPE:
45 lxb_html_tree_parse_error(tree, token,
46 LXB_HTML_RULES_ERROR_DOTOINBEHTMO);
47 break;
48
49 case LXB_TAG__EM_COMMENT: {
50 lxb_dom_comment_t *comment;
51
52 comment = lxb_html_tree_insert_comment(tree, token,
53 lxb_dom_interface_node(tree->document));
54 if (comment == NULL) {
55 return lxb_html_tree_process_abort(tree);
56 }
57
58 break;
59 }
60
61 case LXB_TAG_HTML: {
62 lxb_dom_node_t *node_html;
63 lxb_html_element_t *element;
64
65 element = lxb_html_tree_create_element_for_token(tree, token,
66 LXB_NS_HTML,
67 &tree->document->dom_document.node);
68 if (element == NULL) {
69 tree->status = LXB_STATUS_ERROR_MEMORY_ALLOCATION;
70
71 return lxb_html_tree_process_abort(tree);
72 }
73
74 node_html = lxb_dom_interface_node(element);
75
76 tree->status = lxb_html_tree_insertion_mode_before_html_html(tree,
77 node_html);
78 if (tree->status != LXB_STATUS_OK) {
79 return lxb_html_tree_process_abort(tree);
80 }
81
82 tree->has_explicit_html_tag = true;
83
84 tree->mode = lxb_html_tree_insertion_mode_before_head;
85
86 break;
87 }
88
89 case LXB_TAG__TEXT:
90 tree->status = lxb_html_token_data_skip_ws_begin(token);
91 if (tree->status != LXB_STATUS_OK) {
92 return lxb_html_tree_process_abort(tree);
93 }
94
95 if (token->text_start == token->text_end) {
96 return true;
97 }
98 /* fall through */
99
100 default:
101 return lxb_html_tree_insertion_mode_before_html_anything_else(tree);
102 }
103
104 return true;
105 }
106
107 static bool
lxb_html_tree_insertion_mode_before_html_closed(lxb_html_tree_t * tree,lxb_html_token_t * token)108 lxb_html_tree_insertion_mode_before_html_closed(lxb_html_tree_t *tree,
109 lxb_html_token_t *token)
110 {
111 switch (token->tag_id) {
112 case LXB_TAG_HEAD:
113 case LXB_TAG_BODY:
114 case LXB_TAG_HTML:
115 case LXB_TAG_BR:
116 return lxb_html_tree_insertion_mode_before_html_anything_else(tree);
117
118 default:
119 lxb_html_tree_parse_error(tree, token,
120 LXB_HTML_RULES_ERROR_UNCLTOINBEHTMO);
121 break;
122 }
123
124 return true;
125 }
126
127 lxb_inline bool
lxb_html_tree_insertion_mode_before_html_anything_else(lxb_html_tree_t * tree)128 lxb_html_tree_insertion_mode_before_html_anything_else(lxb_html_tree_t *tree)
129 {
130 lxb_dom_node_t *node_html;
131
132 node_html = lxb_html_tree_create_node(tree, LXB_TAG_HTML, LXB_NS_HTML);
133 if (node_html == NULL) {
134 tree->status = LXB_STATUS_ERROR_MEMORY_ALLOCATION;
135 return lxb_html_tree_process_abort(tree);
136 }
137
138 tree->status = lxb_html_tree_insertion_mode_before_html_html(tree,
139 node_html);
140 if (tree->status != LXB_STATUS_OK) {
141 return lxb_html_tree_process_abort(tree);
142 }
143
144 tree->mode = lxb_html_tree_insertion_mode_before_head;
145
146 return false;
147 }
148
149 lxb_inline lxb_status_t
lxb_html_tree_insertion_mode_before_html_html(lxb_html_tree_t * tree,lxb_dom_node_t * node_html)150 lxb_html_tree_insertion_mode_before_html_html(lxb_html_tree_t *tree,
151 lxb_dom_node_t *node_html)
152 {
153 lxb_status_t status;
154
155 status = lxb_html_tree_open_elements_push(tree, node_html);
156 if (status != LXB_STATUS_OK) {
157 return status;
158 }
159
160 lxb_html_tree_insert_node(lxb_dom_interface_node(tree->document),
161 node_html,
162 LXB_HTML_TREE_INSERTION_POSITION_CHILD);
163
164 lxb_dom_document_attach_element(&tree->document->dom_document,
165 lxb_dom_interface_element(node_html));
166
167 return LXB_STATUS_OK;
168 }
169