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/token.h"
9
10
11 static void
12 lxb_html_tree_insertion_mode_in_table_text_erase(lxb_html_tree_t *tree);
13
14
15 bool
lxb_html_tree_insertion_mode_in_table_text(lxb_html_tree_t * tree,lxb_html_token_t * token)16 lxb_html_tree_insertion_mode_in_table_text(lxb_html_tree_t *tree,
17 lxb_html_token_t *token)
18 {
19 lxb_status_t status;
20 lexbor_str_t *text;
21 lexbor_array_obj_t *pt_list = tree->pending_table.text_list;
22
23 if (token->tag_id == LXB_TAG__TEXT) {
24 if (token->null_count != 0) {
25 lxb_html_tree_parse_error(tree, token,
26 LXB_HTML_RULES_ERROR_NUCH);
27 }
28
29 text = lexbor_array_obj_push(pt_list);
30 if (text == NULL) {
31 tree->status = LXB_STATUS_ERROR_MEMORY_ALLOCATION;
32
33 lxb_html_tree_insertion_mode_in_table_text_erase(tree);
34
35 return lxb_html_tree_process_abort(tree);
36 }
37
38 if (token->null_count != 0) {
39 lxb_html_tree_parse_error(tree, token,
40 LXB_HTML_RULES_ERROR_NUCH);
41
42 tree->status = lxb_html_token_make_text_drop_null(token, text,
43 tree->document->dom_document.text);
44 }
45 else {
46 tree->status = lxb_html_token_make_text(token, text,
47 tree->document->dom_document.text);
48 }
49
50 if (tree->status != LXB_STATUS_OK) {
51 lxb_html_tree_insertion_mode_in_table_text_erase(tree);
52
53 return lxb_html_tree_process_abort(tree);
54 }
55
56 if (text->length == 0) {
57 lexbor_array_obj_pop(pt_list);
58 lexbor_str_destroy(text, tree->document->dom_document.text, false);
59
60 return true;
61 }
62
63 /*
64 * The lxb_html_token_data_skip_ws_begin function
65 * can change token->text_start value.
66 */
67 size_t i_pos = lexbor_str_whitespace_from_begin(text);
68
69 if (i_pos != text->length) {
70 if (!tree->pending_table.have_non_ws) {
71 tree->pending_table.have_non_ws = true;
72 }
73 }
74
75 return true;
76 }
77
78 if (tree->pending_table.have_non_ws) {
79 lxb_html_tree_parse_error(tree, token, LXB_HTML_RULES_ERROR_CHINTATE);
80
81 tree->foster_parenting = true;
82
83 for (size_t i = 0; i < lexbor_array_obj_length(pt_list); i++) {
84 text = lexbor_array_obj_get(pt_list, i);
85
86 status = lxb_html_tree_insertion_mode_in_body_text_append(tree,
87 text);
88 if (status != LXB_STATUS_OK) {
89 lxb_html_tree_insertion_mode_in_table_text_erase(tree);
90
91 return lxb_html_tree_process_abort(tree);
92 }
93 }
94
95 tree->foster_parenting = false;
96 }
97 else {
98 for (size_t i = 0; i < lexbor_array_obj_length(pt_list); i++) {
99 text = lexbor_array_obj_get(pt_list, i);
100
101 tree->status = lxb_html_tree_insert_character_for_data(tree, text,
102 NULL);
103 if (tree->status != LXB_STATUS_OK) {
104 lxb_html_tree_insertion_mode_in_table_text_erase(tree);
105
106 return lxb_html_tree_process_abort(tree);
107 }
108 }
109 }
110
111 tree->mode = tree->original_mode;
112
113 return false;
114 }
115
116 static void
lxb_html_tree_insertion_mode_in_table_text_erase(lxb_html_tree_t * tree)117 lxb_html_tree_insertion_mode_in_table_text_erase(lxb_html_tree_t *tree)
118 {
119 lexbor_str_t *text;
120 lexbor_array_obj_t *pt_list = tree->pending_table.text_list;
121
122 for (size_t i = 0; i < lexbor_array_obj_length(pt_list); i++) {
123 text = lexbor_array_obj_get(pt_list, i);
124
125 lexbor_str_destroy(text, tree->document->dom_document.text, false);
126 }
127 }
128