# Control flow implementation for `rstml`
The collection of `rstml` `CustomNode`s for the control flow.
## Motivation
This crate aims to provide an example of how to extend `rstml` with custom nodes.
Using custom nodes instead of using inner macro calls decreases the complexity of written templates, and allows `rstml` to parse the whole template at once.
## Custom nodes
Custom nodes in `rstml` are allowing external code to extend the `Node` enum. This is useful for supporting
custom syntax that is not common for HTML/XML documents. It is only allowed to be used in the context of `Node`, not in element attributes or node names.
# Control flow implementation
The common use case for custom nodes is implementing if/else operators and loops. This crate provides two different ways of implementing if/else control flow.
## Control flow using tags
The first way is to use custom tags. This is the most native way of implementing control flow in HTML templates since control flow looks like a regular HTML element. The downside of this approach is that it is not possible to properly parse `Rust` expressions inside HTML element attributes.
For example, for ` bar> ` it is hard to determine where the tag with attributes ends and where the content starts.
In this crate, we force the user to use a special delimiter at the end of the tag.
so instead of ` bar> ` we have to write ` bar !> `, where `!>` is a delimiter. This special syntax is used inside `` and `` tags as well.
Example:
```rust
use rstml::{parse2_with_config, node::*};
use rstml_controll_flow::tags::*;
use quote::quote;
let template = quote!{
foo is true
bar is true
foo and bar are false
}
let nodes = parse2_with_config(template, Default::default().with_custom_nodes::())
.unwrap();
```
Note: that `else if` and `else` tags are optional and their content is moved to the fields of the `IfNode`. Other nodes inside the `if` tag are all collected into the `IfNode::body` field, even if they were between `` and `` tags in the example above.
## Controll flow using escape symbol in unquoted text.
The second way is to use the escape symbol in unquoted text.
This approach is more native for `Rust` since it is declared in the same way as in `Rust` code.
The only difference is that the block inside `{}` is not `Rust` code, but `rstml` template.
Example:
```rust
use rstml::{parse2_with_config, node::*};
use rstml_controll_flow::escape::*;
use quote::quote;
let template = quote!{
@if foo {
foo is true
} else if bar {
bar is true
} else {
foo and bar are false
}
};
let nodes = parse2_with_config(template, Default::default().with_custom_nodes::())
```
`EscapedCode` escape character is configurable, and by default uses the "@" symbol.
## Using multiple `CustomNode`s at once
It is also possible to use more than one `CustomNode` at once.
For example, if you want to use both `Conditions` and `EscapedCode` custom nodes.
`rstml-control-flow` crate provides an `ExtendableCustomNode` struct that can be used to combine multiple `CustomNode`s into one. Check out `extendable.rs` docs and tests in `lib.rs` for more details.
```rust