comet-cpp 0.9.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (77) hide show
  1. checksums.yaml +7 -0
  2. data/bin/comet-html +69 -0
  3. data/bin/comet-make +53 -0
  4. data/bin/comet-new +62 -0
  5. data/bin/comet-web +14 -0
  6. data/lib/comet-html/generator.rb +220 -0
  7. data/lib/comet-html/header-generator.rb +145 -0
  8. data/lib/comet-html/parser-binding.rb +42 -0
  9. data/lib/comet-html/parser-class.rb +168 -0
  10. data/lib/comet-html/parser-context.rb +61 -0
  11. data/lib/comet-html/parser-reference.rb +98 -0
  12. data/lib/comet-html/parser-repeater.rb +58 -0
  13. data/lib/comet-html/parser-slot.rb +108 -0
  14. data/lib/comet-html/source-generator.rb +285 -0
  15. data/lib/comet-html/utils.rb +88 -0
  16. data/lib/guard/comet-html.rb +32 -0
  17. data/lib/guard/comet.rb +36 -0
  18. data/vendor/project/Gemfile +4 -0
  19. data/vendor/project/Guardfile +5 -0
  20. data/vendor/project/app/application.hpp +29 -0
  21. data/vendor/project/app/collections/.gitkeep +0 -0
  22. data/vendor/project/app/controllers/.gitkeep +0 -0
  23. data/vendor/project/app/main.cpp +6 -0
  24. data/vendor/project/app/models/.gitkeep +0 -0
  25. data/vendor/project/app/routes.cpp +7 -0
  26. data/vendor/project/app/views/layouts/.gitkeep +0 -0
  27. data/vendor/project/public/index.html +7 -0
  28. data/vendor/src/anchorable_element.hpp +79 -0
  29. data/vendor/src/append_semantics.hpp +73 -0
  30. data/vendor/src/bindable.cpp +99 -0
  31. data/vendor/src/bindable.hpp +106 -0
  32. data/vendor/src/cheerp_parse_cookie_values.cpp +58 -0
  33. data/vendor/src/comment_element.cpp +11 -0
  34. data/vendor/src/comment_element.hpp +17 -0
  35. data/vendor/src/cookies.cpp +94 -0
  36. data/vendor/src/cookies.hpp +60 -0
  37. data/vendor/src/custom_element.hpp +61 -0
  38. data/vendor/src/datatree.cpp +198 -0
  39. data/vendor/src/datatree.hpp +233 -0
  40. data/vendor/src/document.cpp +62 -0
  41. data/vendor/src/document.hpp +31 -0
  42. data/vendor/src/element.cpp +358 -0
  43. data/vendor/src/element.hpp +138 -0
  44. data/vendor/src/events.hpp +76 -0
  45. data/vendor/src/exception.cpp +13 -0
  46. data/vendor/src/exception.hpp +11 -0
  47. data/vendor/src/from_string.cpp +99 -0
  48. data/vendor/src/from_string.hpp +37 -0
  49. data/vendor/src/globals.cpp +6 -0
  50. data/vendor/src/globals.hpp +15 -0
  51. data/vendor/src/http.cpp +93 -0
  52. data/vendor/src/http.hpp +72 -0
  53. data/vendor/src/lexical_cast.hpp +51 -0
  54. data/vendor/src/local_storage.cpp +75 -0
  55. data/vendor/src/local_storage.hpp +53 -0
  56. data/vendor/src/mvc/collection.hpp +154 -0
  57. data/vendor/src/mvc/controller.hpp +59 -0
  58. data/vendor/src/mvc/id_type.hpp +9 -0
  59. data/vendor/src/mvc/layout.hpp +44 -0
  60. data/vendor/src/mvc/model.cpp +89 -0
  61. data/vendor/src/mvc/model.hpp +50 -0
  62. data/vendor/src/object.cpp +71 -0
  63. data/vendor/src/object.hpp +298 -0
  64. data/vendor/src/parse_cookie_values.hpp +12 -0
  65. data/vendor/src/promise.cpp +50 -0
  66. data/vendor/src/promise.hpp +43 -0
  67. data/vendor/src/repeater.hpp +116 -0
  68. data/vendor/src/router.cpp +62 -0
  69. data/vendor/src/router.hpp +34 -0
  70. data/vendor/src/router_base.hpp +107 -0
  71. data/vendor/src/signal.hpp +150 -0
  72. data/vendor/src/slot_element.hpp +61 -0
  73. data/vendor/src/url.cpp +19 -0
  74. data/vendor/src/url.hpp +15 -0
  75. data/vendor/src/window.cpp +22 -0
  76. data/vendor/src/window.hpp +24 -0
  77. metadata +134 -0
@@ -0,0 +1,233 @@
1
+ #ifndef FRONT_DATATREE_HPP
2
+ # define FRONT_DATATREE_HPP
3
+
4
+ # include <functional>
5
+ # include <vector>
6
+ # include <string>
7
+ # include <iostream>
8
+ # include <sstream>
9
+ # include "object.hpp"
10
+ # include <iostream>
11
+
12
+ class DataTree;
13
+
14
+ class Data
15
+ {
16
+ friend class DataTree;
17
+ protected:
18
+ Data(Comet::Object o) : object(o)
19
+ {
20
+ }
21
+
22
+ Data(Comet::Object o, const std::string& k) : object(o), key(k)
23
+ {
24
+ }
25
+
26
+ public:
27
+ Data() : object(Comet::Object())
28
+ {
29
+ }
30
+
31
+ template<typename T>
32
+ T operator[](const std::string& key) const
33
+ {
34
+ std::string as_string = as_object()[key.c_str()];
35
+ std::stringstream stream;
36
+ T output;
37
+
38
+ stream << as_string;
39
+ stream >> output;
40
+ return output;
41
+ }
42
+
43
+ Data operator[](const std::string& k) const
44
+ {
45
+ if (is_null())
46
+ object.set(key, Comet::Object());
47
+ return Data(as_object(), k.c_str());
48
+ }
49
+
50
+ template<typename T>
51
+ T operator[](const char* str) const { return operator[]<T>(std::string(str)); }
52
+ Data operator[](const char* str) const { return operator[](std::string(str)); }
53
+
54
+ Data at(unsigned int i) const;
55
+
56
+ std::vector<std::string> find_missing_keys(const std::vector<std::string>& keys) const;
57
+ bool require(const std::vector<std::string>& keys) const;
58
+
59
+ const std::string& get_path() const { return key; }
60
+ const std::string& get_key() const { return key; }
61
+
62
+ std::size_t count() const;
63
+
64
+ template<typename T>
65
+ T as() const
66
+ {
67
+ std::string as_string = as_object().apply("toString");
68
+ std::stringstream stream;
69
+ T value;
70
+
71
+ stream << as_string;
72
+ stream >> value;
73
+ return value;
74
+ }
75
+
76
+ template<typename T>
77
+ T defaults_to(const T def) const { return exists() ? as<T>() : def; }
78
+
79
+ template<typename T>
80
+ operator T() const
81
+ {
82
+ return as<T>();
83
+ }
84
+
85
+ template<typename T>
86
+ std::vector<T> to_vector() const
87
+ {
88
+ return as_object().to_vector<T>();
89
+ }
90
+
91
+ template<typename T>
92
+ void from_vector(const std::vector<T>& array)
93
+ {
94
+ Comet::ObjectImpl<client::Array> array_object;
95
+
96
+ for (const T& v : array)
97
+ {
98
+ Comet::Object value_object(v);
99
+
100
+ array_object->push(*value_object);
101
+ }
102
+ object.set(key, array_object);
103
+ }
104
+
105
+ template<typename T>
106
+ operator std::vector<T>() const
107
+ {
108
+ return to_vector<T>();
109
+ }
110
+
111
+ template<typename T>
112
+ Data& operator=(const T value)
113
+ {
114
+ Comet::Object value_object(value);
115
+
116
+ object.set(key, value_object);
117
+ return *this;
118
+ }
119
+
120
+ template<typename T>
121
+ Data& operator=(const std::vector<T>& value)
122
+ {
123
+ from_vector(value);
124
+ return *this;
125
+ }
126
+
127
+ Data& operator=(const Data& copy)
128
+ {
129
+ object = copy.object;
130
+ key = copy.key;
131
+ return *this;
132
+ }
133
+
134
+ template<typename T>
135
+ bool operator==(const T value) const
136
+ {
137
+ T self = as_object();
138
+
139
+ return self == value;
140
+ }
141
+
142
+ template<typename T>
143
+ bool operator!=(const T value) const { return !(Data::operator==(value)); }
144
+
145
+ Data operator||(Data value) const
146
+ {
147
+ return exists() ? *this : value;
148
+ }
149
+
150
+ template<typename T>
151
+ T operator||(const T value) const
152
+ {
153
+ return defaults_to<T>(value);
154
+ }
155
+
156
+ void push_back(Data data)
157
+ {
158
+ if (!(exists()))
159
+ object.set(key, Comet::ObjectImpl<client::Array>());
160
+ Comet::ObjectImpl<client::Array> array(*as_object());
161
+
162
+ array->push(*data.as_object());
163
+ }
164
+
165
+ template<typename T>
166
+ void push_back(const T value)
167
+ {
168
+ if (!(exists()))
169
+ object.set(key, Comet::ObjectImpl<client::Array>());
170
+ Comet::ObjectImpl<client::Array> array(*as_object());
171
+ Comet::Object value_object(value);
172
+
173
+ array->push(*value_object);
174
+ }
175
+
176
+ bool is_null() const;
177
+ bool is_blank() const;
178
+ bool is_array() const;
179
+ bool exists() const;
180
+ void destroy();
181
+
182
+ void each(std::function<bool (Data)> functor);
183
+ void each(std::function<bool (const Data)> functor) const;
184
+
185
+ void output(std::ostream& out = std::cout) const;
186
+ std::string to_json() const;
187
+ std::string to_xml() const;
188
+
189
+ void merge(Data data);
190
+ void merge(DataTree datatree);
191
+
192
+ Comet::Object as_object() const
193
+ {
194
+ if (key.length() == 0)
195
+ return object;
196
+ return object[key.c_str()];
197
+ }
198
+
199
+ std::vector<std::string> get_keys() const;
200
+
201
+ mutable Comet::Object object;
202
+ std::string key;
203
+ };
204
+
205
+ template<> bool Data::as<bool>() const;
206
+ template<> std::string Data::as<std::string>() const;
207
+ template<> std::wstring Data::as<std::wstring>() const;
208
+
209
+ class DataTree
210
+ {
211
+ public:
212
+ DataTree() {}
213
+ DataTree(Comet::Object o) : tree(o) {}
214
+
215
+ operator Data() { return as_data(); }
216
+ Data as_data() { return Data(tree); }
217
+ const Data as_data() const { return Data(tree); }
218
+ Data operator[](const std::string& key) { return Data(tree, key.c_str()); }
219
+ const Data operator[](const std::string& key) const { return Data(tree, key.c_str()); }
220
+ void clear() { tree = Comet::Object(); }
221
+
222
+ DataTree& from_json(std::stringstream& stream);
223
+ DataTree& from_json(const std::string& str);
224
+ DataTree& from_json_file(const std::string&);
225
+ std::string to_json() const;
226
+
227
+ Comet::Object as_object() { return tree; }
228
+
229
+ private:
230
+ Comet::Object tree;
231
+ };
232
+
233
+ #endif
@@ -0,0 +1,62 @@
1
+ #include "document.hpp"
2
+ #include "globals.hpp"
3
+ #include <iostream>
4
+
5
+ using namespace Comet;
6
+ using namespace std;
7
+
8
+ Comet::Document Comet::document;
9
+
10
+ Document::Document() : ObjectImpl(&(client::document)), events(make_shared<JavascriptEvents>((client::EventTarget*)&client::document))
11
+ {
12
+ auto callback = [this]() { on_ready_state_changed(); };
13
+
14
+ events->on("readystatechange", callback);
15
+ client::window.setTimeout(cheerp::Callback(callback), 0);
16
+ }
17
+
18
+ Document::ReadyState Document::get_ready_state()
19
+ {
20
+ client::String* str = (*this)->get_readyState();
21
+ std::string ready_state = (std::string)(*(str));
22
+
23
+ if (ready_state == "complete")
24
+ return Complete;
25
+ else if (ready_state == "interactive")
26
+ return Interactive;
27
+ return Loading;
28
+ }
29
+
30
+ void Document::on_ready(function<void ()> callback)
31
+ {
32
+ switch (get_ready_state())
33
+ {
34
+ case Loading:
35
+ on_ready_callbacks.push_back(callback);
36
+ break ;
37
+ default:
38
+ client::window.setTimeout(cheerp::Callback(callback), 0);
39
+ break ;
40
+ }
41
+ }
42
+
43
+ void Document::on_ready_state_changed()
44
+ {
45
+ switch (get_ready_state())
46
+ {
47
+ case Interactive:
48
+ case Complete:
49
+ on_loading_ended();
50
+ break ;
51
+ default:
52
+ break ;
53
+ }
54
+ }
55
+
56
+ void Document::on_loading_ended()
57
+ {
58
+ body = Element((*this)->get_body());
59
+ for (auto callback : on_ready_callbacks)
60
+ callback();
61
+ on_ready_callbacks.empty();
62
+ }
@@ -0,0 +1,31 @@
1
+ #ifndef COMET_DOCUMENT_HPP
2
+ # define COMET_DOCUMENT_HPP
3
+
4
+ # include "object.hpp"
5
+ # include "signal.hpp"
6
+ # include "events.hpp"
7
+ # include <list>
8
+
9
+ namespace Comet
10
+ {
11
+ class Document : public ObjectImpl<client::Document>
12
+ {
13
+ public:
14
+ enum ReadyState { Loading, Interactive, Complete };
15
+
16
+ std::shared_ptr<JavascriptEvents> events;
17
+
18
+ Document();
19
+
20
+ ReadyState get_ready_state();
21
+ void on_ready(std::function<void ()> callback);
22
+
23
+ private:
24
+ void on_ready_state_changed();
25
+ void on_loading_ended();
26
+
27
+ std::list<std::function<void()>> on_ready_callbacks;
28
+ };
29
+ }
30
+
31
+ #endif
@@ -0,0 +1,358 @@
1
+ #include "element.hpp"
2
+ #include "object.hpp"
3
+ #include <algorithm>
4
+
5
+ using namespace std;
6
+ using namespace Comet;
7
+
8
+ static std::map<std::string, std::string> display_style_by_tag = {
9
+ {"div", "block"}, {"tr", "table-row"}, {"td", "table-cell"}, {"th", "table-cell"}, {"table", "table"}
10
+ };
11
+
12
+ static std::string get_default_display_style_for_tag(std::string tag)
13
+ {
14
+ transform(tag.begin(), tag.end(), tag.begin(), [](char c) -> char { return tolower(c); });
15
+ if (display_style_by_tag.find(tag) != display_style_by_tag.end())
16
+ return display_style_by_tag.at(tag);
17
+ return "inline-block";
18
+ }
19
+
20
+ static std::vector<std::string> string_split(const std::string& src, char delimiter)
21
+ {
22
+ vector<string> strings;
23
+ istringstream f(src.c_str());
24
+ string s;
25
+
26
+ while (getline(f, s, delimiter))
27
+ strings.push_back(s);
28
+ return strings;
29
+ }
30
+
31
+ Element::Element() : ObjectImpl(client::document.createElement("div")), events(make_shared<JavascriptEvents>(static_cast<client::HTMLElement*>(ptr)))
32
+ {
33
+ }
34
+
35
+ Element::Element(const client::String& type, const map<string, string>& children) :
36
+ ObjectImpl(client::document.createElement(type)), events(make_shared<JavascriptEvents>(static_cast<client::HTMLElement*>(ptr)))
37
+ {
38
+ attr(children);
39
+ }
40
+
41
+ Element::Element(client::HTMLElement* el) : ObjectImpl(el), events(make_shared<JavascriptEvents>(static_cast<client::HTMLElement*>(ptr)))
42
+ {
43
+ }
44
+
45
+ void Element::destroy()
46
+ {
47
+ if (has_parent())
48
+ (*this)->get_parentElement()->removeChild(**this);
49
+ }
50
+
51
+ bool Element::is_visible() const
52
+ {
53
+ auto* style = (*this)->get_style();
54
+ auto* css_display = style->get_display();
55
+ auto* css_visible = style->get_visibility();
56
+
57
+ return (!css_display || (string)(*css_display) != "none") &&
58
+ (!css_visible || (string)(*css_visible) != "hidden");
59
+ }
60
+
61
+ Element& Element::visible(bool value, const string& _display)
62
+ {
63
+ auto* style = (*this)->get_style();
64
+ string display;
65
+
66
+ if (value)
67
+ {
68
+ if (!_display.length())
69
+ display = get_default_display_style_for_tag(tagName());
70
+ else
71
+ display = _display;
72
+ }
73
+ else
74
+ display = "none";
75
+ style->set_display(display.c_str());
76
+ return *this;
77
+ }
78
+
79
+ bool Element::is_attached() const
80
+ {
81
+ auto* el = (*this)->get_parentElement();
82
+
83
+ while (el)
84
+ {
85
+ if (el == client::document.get_body())
86
+ return true;
87
+ el = el->get_parentElement();
88
+ }
89
+ return false;
90
+ }
91
+
92
+ bool Element::has_parent() const
93
+ {
94
+ return (*this)->get_parentElement() != 0;
95
+ }
96
+
97
+ Element Element::get_parent()
98
+ {
99
+ return Element((*this)->get_parentElement());
100
+ }
101
+
102
+ Element Element::get_next()
103
+ {
104
+ return Element((client::HTMLElement*)((*this)->get_nextElementSibling()));
105
+ }
106
+
107
+ Element& Element::attr(const std::map<std::string, std::string>& attrs)
108
+ {
109
+ for (auto it = attrs.begin() ; it != attrs.end() ; ++it)
110
+ (*this)->setAttribute(it->first.c_str(), it->second.c_str());
111
+ return *this;
112
+ }
113
+
114
+ Element& Element::attr(const std::map<std::string, std::wstring>& attrs)
115
+ {
116
+ for (auto it = attrs.begin() ; it != attrs.end() ; ++it)
117
+ (*this)->setAttribute(it->first.c_str(), it->second.c_str());
118
+ return *this;
119
+ }
120
+
121
+ Element& Element::attr(const std::map<std::string, client::String*>& attrs)
122
+ {
123
+ for (auto it = attrs.begin() ; it != attrs.end() ; ++it)
124
+ (*this)->setAttribute(it->first.c_str(), it->second);
125
+ return *this;
126
+ }
127
+
128
+ Element& Element::attr(const string& name, const string& value)
129
+ {
130
+ (*this)->setAttribute(name.c_str(), value.c_str());
131
+ return *this;
132
+ }
133
+
134
+ string Element::attr(const string& name) const
135
+ {
136
+ if ((*this)->hasAttribute(name.c_str()))
137
+ {
138
+ Comet::Object attribute = (*this)->getAttribute(name.c_str());
139
+
140
+ return attribute;
141
+ }
142
+ return "";
143
+ }
144
+
145
+ static std::string generate_style_attribute(std::map<std::string, std::string> attrs)
146
+ {
147
+ std::string result;
148
+
149
+ for (auto entry : attrs)
150
+ result += entry.first + ':' + entry.second + ';';
151
+ return result;
152
+ }
153
+
154
+ Element& Element::css(const string& name, const string& value)
155
+ {
156
+ auto css_attributes = css();
157
+
158
+ css_attributes[name] = value;
159
+ attr("style", generate_style_attribute(css_attributes));
160
+ return *this;
161
+ }
162
+
163
+ Element& Element::css(const map<string,string>& attrs)
164
+ {
165
+ auto css_attributes = css();
166
+
167
+ for (auto entry : attrs)
168
+ css_attributes[entry.first] = entry.second;
169
+ attr("style", generate_style_attribute(css_attributes));
170
+ return *this;
171
+ }
172
+
173
+ map<string, string> Element::css() const
174
+ {
175
+ map<string, string> results;
176
+ string style = attr("style");
177
+ auto css_attributes = string_split(style, ';');
178
+
179
+ for (auto css_attribute : css_attributes)
180
+ {
181
+ auto delimiter = css_attribute.find(':');
182
+
183
+ if (delimiter != string::npos)
184
+ results.emplace(css_attribute.substr(0, delimiter), css_attribute.substr(delimiter + 1));
185
+ }
186
+ return results;
187
+ }
188
+
189
+ void Element::append_to(client::HTMLElement* el)
190
+ {
191
+ el->appendChild(**this);
192
+ }
193
+
194
+ void Element::append_to(Element& el)
195
+ {
196
+ el->appendChild(static_cast<client::HTMLElement*>(ptr));
197
+ }
198
+
199
+ void Element::insert_before(client::HTMLElement* el)
200
+ {
201
+ if (el)
202
+ {
203
+ auto* parent = el->get_parentElement();
204
+
205
+ if (parent)
206
+ parent->insertBefore(**this, el);
207
+ }
208
+ }
209
+
210
+ void Element::insert_before(Element& el)
211
+ {
212
+ insert_before(static_cast<client::HTMLElement*>(el.ptr));
213
+ }
214
+
215
+ void Element::insert_after(client::HTMLElement* el)
216
+ {
217
+ if (el)
218
+ {
219
+ Comet::Element wrapper(el);
220
+ auto* nextSibling = el->get_nextSibling();
221
+
222
+ if (nextSibling)
223
+ insert_before(static_cast<client::HTMLElement*>(nextSibling));
224
+ else if (wrapper.has_parent())
225
+ append_to(*(wrapper.get_parent()));
226
+ }
227
+ }
228
+
229
+ void Element::insert_after(Element& el)
230
+ {
231
+ insert_after(static_cast<client::HTMLElement*>(el.ptr));
232
+ }
233
+
234
+ bool Element::contains(const client::HTMLElement* source)
235
+ {
236
+ bool result = false;
237
+
238
+ if (**this == source)
239
+ return true;
240
+ each([&result, source](Element& el) -> bool
241
+ {
242
+ result = el.contains(source);
243
+ return !result;
244
+ });
245
+ return result;
246
+ }
247
+
248
+ std::vector<Element> Element::find(const std::string& selector)
249
+ {
250
+ client::NodeList* node_list = (*this)->querySelectorAll(selector.c_str());
251
+ std::vector<Element> results;
252
+
253
+ results.resize(node_list->get_length());
254
+ for (double i = 0 ; i < node_list->get_length() ; ++i)
255
+ results[i] = Element(static_cast<client::HTMLElement*>(node_list->item(i)));
256
+ return results;
257
+ }
258
+
259
+ Element Element::find_one(const std::string& selector)
260
+ {
261
+ return Element(static_cast<client::HTMLElement*>((*this)->querySelector(selector.c_str())));
262
+ }
263
+
264
+ void Element::each(std::function<bool (Element&)> func)
265
+ {
266
+ auto* node_list = (*this)->get_childNodes();
267
+
268
+ for (double i = 0 ; i < node_list->get_length() ; ++i)
269
+ {
270
+ Element child(static_cast<client::HTMLElement*>(node_list->item(i)));
271
+
272
+ if (func(child) == false)
273
+ break ;
274
+ }
275
+ }
276
+
277
+ Element& Element::empty()
278
+ {
279
+ auto* node_list = (*this)->get_childNodes();
280
+
281
+ while (node_list->get_length())
282
+ {
283
+ (*this)->removeChild(node_list->item(0));
284
+ node_list = (*this)->get_childNodes();
285
+ }
286
+ return *this;
287
+ }
288
+
289
+ void Element::toggle_class(const std::string& str, bool set)
290
+ {
291
+ if (has_class(str))
292
+ {
293
+ if (!set)
294
+ remove_class(str);
295
+ }
296
+ else if (set)
297
+ add_class(str);
298
+ }
299
+
300
+ void Element::add_class(const std::string& str)
301
+ {
302
+ auto* class_list = (*this)->get_classList();
303
+
304
+ class_list->add(str.c_str());
305
+ }
306
+
307
+ void Element::remove_class(const std::string& str)
308
+ {
309
+ auto* class_list = (*this)->get_classList();
310
+
311
+ class_list->remove(str.c_str());
312
+ }
313
+
314
+ bool Element::has_class(const std::string& str) const
315
+ {
316
+ auto* class_list = (*this)->get_classList();
317
+
318
+ return class_list->contains(str.c_str());
319
+ }
320
+
321
+ bool Element::has_attribute(const std::string& key) const
322
+ {
323
+ return (*this)->hasAttribute(key.c_str());
324
+ }
325
+
326
+ std::string Element::get_attribute(const std::string& key) const
327
+ {
328
+ client::String* attr_ptr = (*this)->getAttribute(key.c_str());
329
+
330
+ return (std::string)(*attr_ptr);
331
+ }
332
+
333
+ void Element::remove_attribute(const std::string& key)
334
+ {
335
+ (*this)->removeAttribute(key.c_str());
336
+ }
337
+
338
+ std::string Element::get_value() const
339
+ {
340
+ auto* input_el = static_cast<client::HTMLInputElement*>(**this);
341
+ auto* client_string = input_el->get_value();
342
+
343
+ return (std::string)(*client_string);
344
+ }
345
+
346
+ std::string Element::get_text() const
347
+ {
348
+ auto* client_string = (*this)->get_innerText();
349
+
350
+ return (std::string)(*client_string);
351
+ }
352
+
353
+ std::string Element::get_inner_html() const
354
+ {
355
+ auto* client_string = (*this)->get_innerHTML();
356
+
357
+ return (std::string)(*client_string);
358
+ }