Introduction
Rdxl is a set of macros for generating xhtml from Rust. By using rdxl it is possible to intermix xhtml and Rust code to generate interactive documents.
In this book we will document the exact grammar of each rdxl macro and provide many motivating examples and several cheat sheets.
extern crate rdxl; fn main() { println!("{}",rdxl::xhtml!( <p>This copy, version {{rdxl::version}}, is the latest copy of this document</p> <p>We hope that this will satisfy all your web templating needs</p> )); }
HTML Markup
When generating markup, the most common macro to be used is xhtml!. This macro takes mixed markup and rust code to output markup formatted as a String.
Inside xhtml! there are several possible types of markup that can be sent to the formatter:
- XHTML Tags
- Unquoted Text Data
- Quoted Text Data
To generate XHTML Tags, place the tags in angle brackets like normal markup. The tags can be self-closing or contain inner HTML.
extern crate rdxl; fn main() { println!("{}",rdxl::xhtml!( <br/> )); }
To generate Unquoted Text Data it is usually sufficient to place the text directly in the markup. Note that macros are lexed as Rust code before being sent to the macro procedure. This means that not all XHTML can be placed directly inline.
extern crate rdxl; fn main() { println!("{}",rdxl::xhtml!( <p>This paragraph is formatted normally. The breaking spaces are recognized as part of the macro rules.</p> )); }
For Text Data that does not work well with the Rust lexer, the text may be placed inside a rust quoted string literal. This string will be placed directly into the formatted output. It should be noted that raw strings are very a good way to fit even more text data into one quote without the need for escape characters.
extern crate rdxl; fn main() { println!("{}",rdxl::xhtml!( r#"((((( the lexer expects closing braces, brackets, and parentheses [[[[ but what do we care. {{"# )); }
Rust Code
Rust code greatly enhances the generative capabilities of the Rdxl macro rules. Most rust expressions and statements may be placed inside of Rdxl markup and generate code nearly identical to what is stated. This is very helpful not only for creating new powerful abstractions, but also for fixing bugs: error messages for syntax or type errors are correctly tracked and blamed with the same helpful error formatting that Rust is so well known for.
In Rdxl, Rust code is divided into two kinds of syntax expressions: Rust statements and Rust expressions. The difference between a statement or expression is always determined by syntax rather than inference. Expressions always emit a value that implements the Display trait as the return value of the expression. Statements may emit data directly to the string buffer but never as the return value of the statement.
Both expressions and statements are surrounded by double braces to signify that they should be interpreted as Rust code rather than XHTML.
A simple example of a rust expression is a variable interpolated into the markup:
extern crate rdxl; fn main() { let x = 5; println!("{}", xhtml!( These strings are literals, but {{x}} is a variable. )); }
For a complete reference of all expressions, see Chapter 5: Expression Reference.
A simple statement would be a for loop:
#![allow(unused_variables)] fn main() { println!("{}", xhtml!( {{ for x in 0..10 {{ These strings are literals, but {{x}} is a variable. }} }} )); }
For a complete reference of all statements, see Chapter 6: Statement Reference.
Markup Reference
All html tags may be used directly in the body of the macro invocation. Most tag attributes may be used normally as well. Some tag attribute names, for example those with dashes in them, confuse the Rust lexer and therefore should be quoted. All strings are valid attribute names as long as they are quoted as a string literal.
extern crate rdxl; fn main() { println!("{}", xhtml!( <a href="/this_is_ok" "this-must-be-quoted"="abcd">body of link</a> )); }
Rust expressions may be interpolated as attribute values. To insert a Rust expression in attribute position, use the double braces format. When rust expressions are used as attributes, the string value is quoted and escape characters are inserted in place of double quotes etc.
extern crate rdxl; fn main() { let a_class = "my_class"; let a_style = "position:absolute; top:0; left:0;"; println!("{}", xhtml!( <div class={{a_class}} style={{a_style}}>inner html</div> )); }
Expression Reference
All interpolated Rust code is interpreted as an expression provided that
- The snippet does not start with a reserved statement keyword
- The snippet does not end with a semicolon
The statement keywords are: if, let, for, while, loop, and match.
extern crate rdxl; fn main() { let a_flag = true; println!("{}", xhtml!( {{ if a_flag {{ this is a statement }} }} {{ (if a_flag { "this is" } else { "an expression" }) }} )); }
Aside from these reservations, all Rust code may be used as expressions as long as they return a value that implements the Display trait.
extern crate rdxl; fn main() { println!("{}", xhtml!( {{ "ab" }} {{ 'c' }} {{ format!("{} {}", 2, 3) }} {{ true }} )); }