Expand description
An API for building HTML documents in Rust.
- It’s Just Rust Code.
- Safely set attributes and content on HTML elements.
- Link css & javascript snippets to HTML
elements, such that those snippets appear when the linked element is displayed.
- CSS & JS assets are included in the final HTML output.
The crate also implements a set of core css components so you don’t have to
§Example
use toph::{attr, Node, tag::*};
let navigation = [("Home", "/about me"), ("Posts", "/posts")];
let mut doc = [
doctype_,
html_.with(attr![lang="en"])
.set([
head_.set([title_.set(["My Webpage"])]),
body_.set([
ul_.with(attr![id="navigation"])
.set(
navigation.into_iter().map(|(caption, url)| {
li_.set([a_.with(attr![href=url]).set([caption])])
}).collect::<Vec<_>>()
),
h1_.stylesheet("h1 { text-decoration: underline; }")
.set(["My Webpage"])
])
])
];
assert_eq!(
Node::render_pretty(doc),
r#"<!DOCTYPE html>
<html lang="en">
<head>
<title>
My Webpage
</title>
<style>
h1 { text-decoration: underline; }
</style>
</head>
<body>
<ul id="navigation">
<li>
<a href="/about%20me">
Home
</a>
</li>
<li>
<a href="/posts">
Posts
</a>
</li>
</ul>
<h1>
My Webpage
</h1>
</body>
</html>
"#);
§XSS Prevention
A couple measures are taken to protect against Cross-site scripting attacks (XSS):
- Strings are appropriately encoded in HTML, attribute and URL contexts:
use toph::{attr, tag::*, Node};
let xss_attr_attempt = r#"" onclick="alert(1)""#;
let xss_attempt = r#"<script>alert(1)"#;
let url = "/path with space";
let mut span = span_
.with(attr![class=xss_attr_attempt])
.set([xss_attempt]);
let mut anchor = a_
.with(attr![href=url])
.set(["A link"]);
assert_eq!(
Node::render([span]),
r#"<span class="" onclick="alert(1)""><script>alert(1)</span>"#
);
assert_eq!(
Node::render([anchor]),
r#"<a href="/path%20with%20space">A link</a>"#
);
- JavaScript & CSS snippets can only be set using literal (i.e.
'static
) string slices.- It is frequently useful to parameterize styles though, so the
var
method is provided. - To include files, use
include_str
- It is frequently useful to parameterize styles though, so the
use toph::{tag::*, Node};
let user_input = "1rem";
let css = format!("p {{ font-size: {}; }}", user_input);
// This does not compile
// let mut html = html_.set([ head_, p_.stylesheet(css)]);
// Neither does this
// let mut html = html_.set([ head_, p_.stylesheet(&css)]);
// Technically, you _could_ leak the string...
// Why you would want to leak memory for this purpose is beyond me.
// You are on your own.
// let mut html = html_.set([ head_, p_.stylesheet(css.leak())]);
// Set snippets using string literals
// Parameterize with css custom variables & `var()`
let css = "p { font-size: var(--font-size); }";
let mut html = html_.set([
head_,
p_.stylesheet(css).var("font-size", user_input),
]);
assert_eq!(
Node::render_pretty([html]),
r#"<html>
<head>
<style>
p { font-size: var(--font-size); }
</style>
</head>
<p style="--font-size: 1rem;">
</p>
</html>
"#);
Modules§
- Composable CSS Layout primitives and components
- HTML Elements
Macros§
- Attribute list builder
Structs§
- An HTML Node. All tag functions are instances of this type.