1use crate::virtual_dom::{At, Attrs};
7
8#[macro_export]
39macro_rules! with_dollar_sign {
40 ($($body:tt)*) => {
41 macro_rules! __with_dollar_sign { $($body)* }
42 __with_dollar_sign!($);
43 }
44}
45
46#[macro_export]
96macro_rules! struct_urls {
97 () => {
98 pub struct Urls<'a> {
99 base_url: std::borrow::Cow<'a, $crate::browser::Url>,
100 }
101
102 impl<'a> Urls<'a> {
103 pub fn new(base_url: impl Into<std::borrow::Cow<'a, $crate::browser::Url>>) -> Self {
111 Self {
112 base_url: base_url.into(),
113 }
114 }
115
116 pub fn base_url(self) -> $crate::browser::Url {
126 self.base_url.into_owned()
127 }
128 }
129 };
130}
131
132macro_rules! element {
136 ($($Tag:ident => $Tag_camel:ident);+) => {
138 with_dollar_sign! {
140 ($d:tt) => {
141 $(
142 #[macro_export]
143 macro_rules! $Tag {
144 ( $d($d part:expr),* $d(,)? ) => {
145 {
146 #[allow(unused_mut)]
147 let mut el = El::empty($crate::virtual_dom::Tag::$Tag_camel);
148 $d (
149 $d part.update_el(&mut el);
150 )*
151 $crate::virtual_dom::Node::Element(el)
152 }
153 };
154 }
155 )+
156 }
157 }
158 }
159}
160macro_rules! element_svg {
162 ($($Tag:ident => $Tag_camel:ident);+) => {
164 with_dollar_sign! {
166 ($d:tt) => {
167 $(
168 #[macro_export]
169 macro_rules! $Tag {
170 ( $d($d part:expr),* $d(,)? ) => {
171 {
172 #[allow(unused_mut)]
173 let mut el = El::empty_svg($crate::virtual_dom::Tag::$Tag_camel);
174 $d ( $d part.update_el(&mut el); )*
175 $crate::virtual_dom::Node::Element(el)
176 }
177 };
178 }
179 )+
180 }
181 }
182 }
183}
184
185element! {
188 address => Address; article => Article; aside => Aside; footer => Footer;
189 header => Header; h1 => H1;
190 h2 => H2; h3 => H3; h4 => H4; h5 => H5; h6 => H6;
191 hgroup => Hgroup; main => Main; nav => Nav; section => Section;
192
193 blockquote => BlockQuote;
194 dd => Dd; dir => Dir; div => Div; dl => Dl; dt => Dt; figcaption => FigCaption; figure => Figure;
195 hr => Hr; li => Li; ol => Ol; p => P; pre => Pre; ul => Ul;
196
197 a => A; abbr => Abbr;
198 b => B; bdi => Bdi; bdo => Bdo; br => Br; cite => Cite; code => Code; data => Data;
199 dfn => Dfn; em => Em; i => I; kbd => Kbd; mark => Mark; q => Q; rb => Rb;
200 rp => Rp; rt => Rt; rtc => Rtc; ruby => Ruby; s => S; samp => Samp; small => Small;
201 span => Span; strong => Strong; sub => Sub; sup => Sup; time => Time; tt => Tt;
202 u => U; var => Var; wbr => Wbr;
203
204 area => Area; audio => Audio; img => Img; map => Map; track => Track; video => Video;
205
206 applet => Applet; embed => Embed; iframe => Iframe;
207 noembed => NoEmbed; object => Object; param => Param; picture => Picture; source => Source;
208
209 canvas => Canvas; noscript => NoScript; Script => Script;
210
211 del => Del; ins => Ins;
212
213 caption => Caption; col => Col; colgroup => ColGroup; table => Table; tbody => Tbody;
214 td => Td; tfoot => Tfoot; th => Th; thead => Thead; tr => Tr;
215
216 button => Button; datalist => DataList; fieldset => FieldSet; form => Form; input => Input;
217 label => Label; legend => Legend; meter => Meter; optgroup => OptGroup; option => Option;
218 output => Output; progress => Progress; select => Select; textarea => TextArea;
219
220 details => Details; dialog => Dialog; menu => Menu; menuitem => MenuItem; summary => Summary;
221
222 content => Content; element => Element; shadow => Shadow; slot => Slot; template => Template
223}
224
225element_svg! {
227 line_ => Line; rect => Rect; circle => Circle; ellipse => Elipse; polygon => Polygon; polyline => Polyline;
230 mesh => Mesh; path => Path;
231 defs => Defs; g => G; marker => Marker; mask => Mask;
233 pattern => Pattern; svg => Svg; switch => Switch; symbol => Symbol; unknown => Unknown;
235 linearGradient => LinearGradient; radialGradient => RadialGradient; meshGradient => MeshGradient;
237 stop => Stop;
238 image => Image;
240 r#use => Use;
242 altGlyph => AltGlyph; altGlyphDef => AltGlyphDef; altGlyphItem => AltGlyphItem; glyph => Glyph;
244 glyphRef => GlyphRef; textPath => TextPath; text => Text; tref => TRef; tspan => TSpan;
245 clipPath => ClipPath; cursor => Cursor; filter => Filter; foreignObject => ForeignObject;
247 hatchpath => HatchPath; meshPatch => MeshPatch; meshrow => MeshRow; view => View;
248 animate => Animate; animateColor => AnimateColor; animateMotion => AnimateMotion;
252 animateTransform => AnimateTransform; discard => Discard; mpath => Mpath; set => Set;
253 desc => Desc; metadata => Metadata; title => Title;
255 feBlend => FeBlend; feColorMatrix => FeColorMatrix; feComponentTransfer => FeComponentTransfer;
257 feComposite => FeComposite; feConvolveMatrix => FeConvolveMatrix;
258 feDiffuseLighting => FeDiffuseLighting; feDisplacementMap => FeDisplacementMap;
259 feDropShadow => FeDropShadow; feFlood => FeFlood; feFuncA => FeFuncA; feFuncB => FeFuncB;
260 feFuncG => FeFuncG; feFuncR => FeFuncR; feGaussianBlur => FeGaussianBlur; feImage => FeImage;
261 feMerge => FeMerge; feMergeNode => FeMergeNode; feMorphology => FeMorphology;
262 feOffset => FeOffset; feSpecularLighting => FeSpecularLighting; feTile => FeTile;
263 feTurbulence => FeTurbulence;
264 font => Font; hkern => HKern; vkern => VKern;
266 hatch => Hatch; solidcolor => SolidColor
269}
270
271#[macro_export]
272macro_rules! empty {
273 () => {
274 $crate::virtual_dom::Node::Empty
275 };
276}
277
278#[macro_export]
279macro_rules! raw {
280 ($raw_html:expr) => {
281 Node::from_html(None, $raw_html)
282 };
283}
284
285#[macro_export]
286macro_rules! raw_svg {
287 ($raw_svg:expr) => {
288 Node::from_html(Some(&Namespace::Svg), $raw_svg)
289 };
290}
291
292#[macro_export]
293macro_rules! plain {
294 ($text:expr) => {
295 $crate::virtual_dom::Node::new_text($text)
296 };
297}
298
299#[macro_export]
300macro_rules! custom {
301 ( $($part:expr),* $(,)? ) => {
302 {
303 let default_tag_name = "missing-tag-name";
304 let mut el = El::empty($crate::virtual_dom::Tag::from(default_tag_name));
305 $ ( $part.update_el(&mut el); )*
306
307 if let $crate::virtual_dom::Tag::Custom(tag_name) = &el.tag {
308 let tag_changed = tag_name != default_tag_name;
309 assert!(tag_changed, "Tag has not been set in `custom!` element. Add e.g. `Tag::from(\"code-block\")`.");
310 }
311
312 $crate::virtual_dom::Node::Element(el)
313 }
314 };
315}
316
317#[macro_export]
319macro_rules! attrs {
320 { $($key:expr => $value:expr $(;)?$(,)?)* } => {
321 {
322 let mut vals = IndexMap::new();
323 $(
324 vals.insert($key.into(), (&$value).into());
328 )*
329 $crate::virtual_dom::Attrs::new(vals)
330 }
331 };
332}
333
334#[deprecated(since = "0.8.0", note = "use [`C!`](macro.C!.html) instead")]
335#[macro_export]
337macro_rules! class {
338 { $($class:expr $(=> $predicate:expr)? $(,)?)* } => {
339 {
340 let mut result = $crate::virtual_dom::Attrs::empty();
341 let mut classes = Vec::new();
342 $(
343 {
345 $(
346 if !$predicate { return }
347 )?
348 classes.push($class);
349 };
350 )*
351 result.add_multiple(At::Class, &classes);
352 result
353 }
354 };
355}
356
357#[macro_export]
368macro_rules! C {
369 ( $($class:expr $(,)?)* ) => {
370 {
371 let mut all_classes = Vec::new();
372 $(
373 $crate::shortcuts::_fill_all_classes(&mut all_classes, $class.to_classes());
374 )*
375 $crate::shortcuts::_all_classes_to_attrs(&all_classes)
376 }
377 };
378}
379
380pub fn _fill_all_classes(all_classes: &mut Vec<String>, classes: Option<Vec<String>>) {
381 if let Some(classes) = classes {
382 for class in classes {
383 if !class.is_empty() {
384 all_classes.push(class);
385 }
386 }
387 }
388}
389
390pub fn _all_classes_to_attrs(all_classes: &[String]) -> Attrs {
391 let mut attrs = Attrs::empty();
392 if !all_classes.is_empty() {
393 attrs.add_multiple(
394 At::Class,
395 &all_classes.iter().map(String::as_str).collect::<Vec<_>>(),
396 );
397 }
398 attrs
399}
400
401#[macro_export]
417macro_rules! IF {
418 ( $predicate:expr => $value:expr ) => {{
419 if $predicate {
421 Some($value)
422 } else {
423 None
424 }
425 }};
426}
427
428#[macro_export]
430macro_rules! id {
431 { $id:expr } => {
432 {
433 $crate::virtual_dom::Attrs::from_id($id)
434 }
435 };
436}
437
438#[macro_export]
442macro_rules! style {
443 { $($key:expr => $value:expr $(;)?$(,)?)* } => {
444 {
445 #[allow(unused_imports)]
446 use $crate::virtual_dom::values::{
447 ToCSSValueForCSSValue, ToCSSValueForOptionToString, ToCSSValueForToString
448 };
449 let mut vals = IndexMap::new();
450 $(
451 vals.insert($key.into(), ($value).to_css_value());
452 )*
453 $crate::virtual_dom::Style::new(vals)
454 }
455 };
456}
457
458#[macro_export]
459macro_rules! nodes {
478 ( $($element:expr $(,)?)* ) => {
479 {
480 use $crate::virtual_dom::IntoNodes;
481 let mut nodes = Vec::new();
482 $(
483 nodes.append(&mut ($element).into_nodes());
484 )*
485 nodes
486 }
487 };
488}
489
490#[macro_export]
492macro_rules! key_value_pairs {
493 { $($key:expr => $value:expr),* $(,)? } => {
494 {
495 let mut result = IndexMap::new();
496 $(
497 result.insert($key.to_string(), $value.to_string());
500 )*
501 result
502 }
503 };
504}