1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
/// Builds a Rust struct that represents an HTML component.
///
/// See documentation on `html!` for more details on the syntax to use
);
)*
Component
}
};
// Specify element name, attributes and text
=> ;
// Specify element name, attributes and text from a variable
=> ;
// Specify element name, attributes and at least one child component
=> ;
// Specify element name, attributes and child components specified in a vector or array
=> ;
}
/// Generates an HTML string using the inputted syntax
///### Creating a Text Element
///#### Using a String Literal
///
/// ```text
/// html!(div (style = "border: 1px solid black;" class = "Hello") "Hello World");
/// ```
///
/// Will create the following string of HTML that consists of a `div` with a `style` attribute that creates a black border, a `class` attribute set to `Hello` and text set to `"Hello World"`
///
/// ```text
/// "<div style=\"border: 1px solid black;\" class=\"Hello\">Hello World</div>"
/// ```
/// This renders as follows in the browser:
///
/// <div style="border: 1px solid black;" class="Hello">Hello World</div>
///
///
/// The first token (here `div`) specifies the name of the element.
///
///The set of parentheses `()` contains the attributes for the element. The attribute name comes before the `=` and the attribute value after and is in double quotation marks. Different attributes are separated by whitespace.
///
///The text in double quotation marks at the end of the content specifies the text content `"Hello World"`.
///
///#### Using a Variable
///The text can also be derived from a variable. In this case surround the variable with curly brackets `{}`
///
///```text
///let example_text = "Hello World";
///
///html!(div (style = "border: 1px solid black;" class = "Hello") {example_text});
///```
///
///gives the same result as before:
///
///```text
///"<div style=\"border: 1px solid black;\" class=\"Hello\">Hello World</div>"
///```
///
///### Creating an Element with No Attributes or Content
///
///Both `html!(div)` and `html!(div ())` will create a string of HTML consisting of an empty div with no styling
///```text
///"<div></div>"
///```
///
///Void elements should not have end tags and this is handled accordingly. For example `html!(hr)` will return `"<hr />"`
///
///### Creating Elements that Contain other Elements
///
///```text
///html!(ul () [el!(li () "First Sibling")] [el!(li () "Second Sibling")])
///```
///
///Will create the following string of HTML that consists of an unordered list with two items
///
///```text
///"<ul><li>First Sibling</li><li>Second Sibling</li></ul>"
///```
///
///In the browser this renders as
///
///<ul><li>First Sibling</li><li>Second Sibling</li></ul>
///
///Each child component is surrounded by square brackets `[]` and is inputted into the macro `el!` which creates the component. Multiple specified child components are treated as siblings.
///
///The result from `el!(li () "Second Sibling")` could have been stored in a variable and the variable used instead as follows:
///
///```text
///let second_sibling = el!(li () "Second Sibling");
///let result = html!(ul()[el!(li () "First Sibling")][second_sibling]);
///```
/// This would return the same HTML String.
///### Where Child Elements are Specified through a Vector or an Array
///
///```text
///let example_list = [
/// el!(li () "First Sibling"),
/// el!(li () "Second Sibling")
///];
///
///html!(ul () vec[example_list])
///```
///
///Will create the following string of HTML that consists of an unordered list with two items
///
///```text
///"<ul><li>First Sibling</li><li>Second Sibling</li></ul>"
///```
///
///In the browser this renders as
///
///<ul><li>First Sibling</li><li>Second Sibling</li></ul>
///
///
///Inserting the text `vec` before the square brackets `[]` tells the macro to expect a vector or array.
///
/// Takes a String and swaps the placeholder text `{COMPONENT}` for the HTML String built using the provided syntax
///
/// First specify the String containing the placeholder text `{COMPONENT}`. This string should be inserted in curly brackets `{}` and have a comma inserted after the brackets.
/// Second specify the syntax describing the element to be inserted.
/// See documentation on `html!` for more details on the syntax to use.
/// ```text
/// let test_contents = String::from("<div>{COMPONENT}</div>");
///
/// let result = insert_html!({test_contents}, span () "Hello World");
///
/// assert_eq!(result, "<div><span>Hello World</span></div>");
///
/// ```