diff --git a/benchmarks/benches/askama.rs b/benchmarks/benches/askama.rs
index b2c9dae..0a12ecc 100644
--- a/benchmarks/benches/askama.rs
+++ b/benchmarks/benches/askama.rs
@@ -5,7 +5,8 @@ extern crate test;
 use askama::Template;
 
 #[derive(Template)]
-#[template(source = r#"
+#[template(
+    source = r#"
 <html>
   <head>
     <title>{{year}}</title>
@@ -20,29 +21,48 @@ use askama::Template;
     {% endfor %}
     </ul>
   </body>
-</html>"#, ext="html")]
+</html>"#,
+    ext = "html"
+)]
 
 struct BenchTemplate {
     year: &'static str,
-    teams: Vec<Entry>
+    teams: Vec<Entry>,
 }
 
 struct Entry {
     name: &'static str,
-    score: u16
+    score: u16,
 }
 
 #[bench]
 fn render_template(b: &mut test::Bencher) {
-    let teams = vec![Entry {name: "Jiangsu",   score: 43},
-                     Entry {name: "Beijing",   score: 27},
-                     Entry {name: "Guangzhou", score: 22},
-                     Entry {name: "Shandong",  score: 12}];
-    let hello = test::black_box(BenchTemplate{ year: "2015", teams });
+    let teams = vec![
+        Entry {
+            name: "Jiangsu",
+            score: 43,
+        },
+        Entry {
+            name: "Beijing",
+            score: 27,
+        },
+        Entry {
+            name: "Guangzhou",
+            score: 22,
+        },
+        Entry {
+            name: "Shandong",
+            score: 12,
+        },
+    ];
+    let hello = test::black_box(BenchTemplate {
+        year: "2015",
+        teams,
+    });
     b.iter(|| {
         // Instead of simply call hello.render().unwrap(), rendering to
         // a string with a good capacity gives a ~10% speed increase here
-       let mut s = String::with_capacity(500);
-       hello.render_into(&mut s).unwrap();
+        let mut s = String::with_capacity(500);
+        hello.render_into(&mut s).unwrap();
     });
 }
diff --git a/benchmarks/benches/complicated_maud.rs b/benchmarks/benches/complicated_maud.rs
index 8d0a02f..2e27ef0 100644
--- a/benchmarks/benches/complicated_maud.rs
+++ b/benchmarks/benches/complicated_maud.rs
@@ -3,7 +3,7 @@
 
 extern crate test;
 
-use maud::{Markup, html};
+use maud::{html, Markup};
 
 #[derive(Debug)]
 struct Entry {
@@ -12,12 +12,12 @@ struct Entry {
 }
 
 mod btn {
-    use maud::{Markup, Render, html};
+    use maud::{html, Markup, Render};
 
     #[derive(Copy, Clone)]
     pub enum RequestMethod {
         Get,
-        Post
+        Post,
     }
 
     #[derive(Copy, Clone)]
@@ -77,24 +77,39 @@ fn layout<S: AsRef<str>>(title: S, inner: Markup) -> Markup {
 fn render_complicated_template(b: &mut test::Bencher) {
     let year = test::black_box("2015");
     let teams = test::black_box(vec![
-        Entry { name: "Jiangsu", score: 43 },
-        Entry { name: "Beijing", score: 27 },
-        Entry { name: "Guangzhou", score: 22 },
-        Entry { name: "Shandong", score: 12 },
+        Entry {
+            name: "Jiangsu",
+            score: 43,
+        },
+        Entry {
+            name: "Beijing",
+            score: 27,
+        },
+        Entry {
+            name: "Guangzhou",
+            score: 22,
+        },
+        Entry {
+            name: "Shandong",
+            score: 12,
+        },
     ]);
     b.iter(|| {
         use crate::btn::{Button, RequestMethod};
-        layout(format!("Homepage of {}", year), html! {
-            h1 { "Hello there!" }
+        layout(
+            format!("Homepage of {}", year),
+            html! {
+                h1 { "Hello there!" }
 
-            @for entry in &teams {
-                div {
-                    strong { (entry.name) }
-                    (Button::new("Edit", "edit"))
-                    (Button::new("Delete", "edit")
-                                .with_method(RequestMethod::Post))
+                @for entry in &teams {
+                    div {
+                        strong { (entry.name) }
+                        (Button::new("Edit", "edit"))
+                        (Button::new("Delete", "edit")
+                                    .with_method(RequestMethod::Post))
+                    }
                 }
-            }
-        })
+            },
+        )
     });
 }
diff --git a/benchmarks/benches/handlebars.rs b/benchmarks/benches/handlebars.rs
index 8181ea6..01e8f44 100644
--- a/benchmarks/benches/handlebars.rs
+++ b/benchmarks/benches/handlebars.rs
@@ -4,8 +4,8 @@
 
 extern crate test;
 
-use serde_json::value::{Map, Value as Json};
 use handlebars::{to_json, Handlebars};
+use serde_json::value::{Map, Value as Json};
 
 static SOURCE: &'static str = "<html>
   <head>
@@ -30,14 +30,12 @@ fn make_data() -> Map<String, Json> {
 
     let mut teams = Vec::new();
 
-    for &(name, score) in
-        &[
-            ("Jiangsu", 43u16),
-            ("Beijing", 27u16),
-            ("Guangzhou", 22u16),
-            ("Shandong", 12u16),
-        ]
-    {
+    for &(name, score) in &[
+        ("Jiangsu", 43u16),
+        ("Beijing", 27u16),
+        ("Guangzhou", 22u16),
+        ("Shandong", 12u16),
+    ] {
         let mut t = Map::new();
         t.insert("name".to_string(), to_json(&name));
         t.insert("score".to_string(), to_json(&score));
@@ -51,7 +49,8 @@ fn make_data() -> Map<String, Json> {
 #[bench]
 fn render_template(b: &mut test::Bencher) {
     let mut handlebars = Handlebars::new();
-    handlebars.register_template_string("table", SOURCE.to_string())
+    handlebars
+        .register_template_string("table", SOURCE.to_string())
         .expect("Invalid template format");
 
     let data = make_data();
diff --git a/benchmarks/benches/horrorshow.rs b/benchmarks/benches/horrorshow.rs
index 76fbe56..5e483a1 100644
--- a/benchmarks/benches/horrorshow.rs
+++ b/benchmarks/benches/horrorshow.rs
@@ -15,10 +15,22 @@ struct Entry {
 fn render_template(b: &mut test::Bencher) {
     let year = test::black_box("2015");
     let teams = test::black_box(vec![
-        Entry { name: "Jiangsu", score: 43 },
-        Entry { name: "Beijing", score: 27 },
-        Entry { name: "Guangzhou", score: 22 },
-        Entry { name: "Shandong", score: 12 },
+        Entry {
+            name: "Jiangsu",
+            score: 43,
+        },
+        Entry {
+            name: "Beijing",
+            score: 27,
+        },
+        Entry {
+            name: "Guangzhou",
+            score: 22,
+        },
+        Entry {
+            name: "Shandong",
+            score: 12,
+        },
     ]);
     b.iter(|| {
         (html! {
@@ -40,6 +52,8 @@ fn render_template(b: &mut test::Bencher) {
                     }
                 }
             }
-        }).into_string().unwrap()
+        })
+        .into_string()
+        .unwrap()
     });
 }
diff --git a/benchmarks/benches/liquid.rs b/benchmarks/benches/liquid.rs
index e2baa0a..9db5515 100644
--- a/benchmarks/benches/liquid.rs
+++ b/benchmarks/benches/liquid.rs
@@ -2,8 +2,8 @@
 
 extern crate test;
 
-use liquid::ParserBuilder;
 use liquid::model::{Object, Value};
+use liquid::ParserBuilder;
 
 static SOURCE: &'static str = "<html>
   <head>
@@ -30,7 +30,13 @@ fn make_team(name: &'static str, score: u16) -> Value {
 
 #[bench]
 fn render_template(b: &mut test::Bencher) {
-    let template = test::black_box(ParserBuilder::with_stdlib().build().unwrap().parse(SOURCE).unwrap());
+    let template = test::black_box(
+        ParserBuilder::with_stdlib()
+            .build()
+            .unwrap()
+            .parse(SOURCE)
+            .unwrap(),
+    );
     let mut globals = test::black_box({
         let mut globals = Object::new();
         globals.insert("year".into(), Value::scalar(2015));
diff --git a/benchmarks/benches/maud.rs b/benchmarks/benches/maud.rs
index dd54324..adaf4ed 100644
--- a/benchmarks/benches/maud.rs
+++ b/benchmarks/benches/maud.rs
@@ -15,10 +15,22 @@ struct Entry {
 fn render_template(b: &mut test::Bencher) {
     let year = test::black_box("2015");
     let teams = test::black_box(vec![
-        Entry { name: "Jiangsu", score: 43 },
-        Entry { name: "Beijing", score: 27 },
-        Entry { name: "Guangzhou", score: 22 },
-        Entry { name: "Shandong", score: 12 },
+        Entry {
+            name: "Jiangsu",
+            score: 43,
+        },
+        Entry {
+            name: "Beijing",
+            score: 27,
+        },
+        Entry {
+            name: "Guangzhou",
+            score: 22,
+        },
+        Entry {
+            name: "Shandong",
+            score: 12,
+        },
     ]);
     b.iter(|| {
         html! {
diff --git a/benchmarks/benches/tera.rs b/benchmarks/benches/tera.rs
index 3299315..6197f4c 100644
--- a/benchmarks/benches/tera.rs
+++ b/benchmarks/benches/tera.rs
@@ -34,12 +34,27 @@ fn render_template(b: &mut test::Bencher) {
 
     let context = test::black_box({
         let mut context = Context::new();
-        context.insert("teams", &[
-            Entry { name: "Jiangsu", score: 43 },
-            Entry { name: "Beijing", score: 27 },
-            Entry { name: "Guangzhou", score: 22 },
-            Entry { name: "Shandong", score: 12 },
-        ]);
+        context.insert(
+            "teams",
+            &[
+                Entry {
+                    name: "Jiangsu",
+                    score: 43,
+                },
+                Entry {
+                    name: "Beijing",
+                    score: 27,
+                },
+                Entry {
+                    name: "Guangzhou",
+                    score: 22,
+                },
+                Entry {
+                    name: "Shandong",
+                    score: 12,
+                },
+            ],
+        );
         context.insert("year", &"2015");
         context
     });
diff --git a/docs/src/main.rs b/docs/src/main.rs
index 6909131..19d8121 100644
--- a/docs/src/main.rs
+++ b/docs/src/main.rs
@@ -1,18 +1,18 @@
 #![feature(proc_macro_hygiene)]
 
-use comrak::{self, Arena, ComrakOptions};
 use comrak::nodes::{AstNode, NodeCodeBlock, NodeHeading, NodeHtmlBlock, NodeLink, NodeValue};
+use comrak::{self, Arena, ComrakOptions};
 use serde_json;
-use std::error::Error;
 use std::env;
+use std::error::Error;
 use std::fs::{self, File};
 use std::io::{self, BufReader};
 use std::mem;
 use std::path::Path;
 use std::string::FromUtf8Error;
-use syntect::parsing::SyntaxSet;
 use syntect::highlighting::{Color, ThemeSet};
 use syntect::html::highlighted_html_for_string;
+use syntect::parsing::SyntaxSet;
 
 use crate::page::Page;
 use crate::string_writer::StringWriter;
@@ -24,12 +24,15 @@ mod views;
 fn main() -> Result<(), Box<dyn Error>> {
     let args = env::args().collect::<Vec<_>>();
     if args.len() >= 3 && &args[1] == "build-nav" && args[3..].iter().all(|arg| arg.contains(":")) {
-        let entries = args[3..].iter().map(|arg| {
-            let mut splits = arg.splitn(2, ":");
-            let slug = splits.next().unwrap();
-            let input_path = splits.next().unwrap();
-            (slug, input_path)
-        }).collect::<Vec<_>>();
+        let entries = args[3..]
+            .iter()
+            .map(|arg| {
+                let mut splits = arg.splitn(2, ":");
+                let slug = splits.next().unwrap();
+                let input_path = splits.next().unwrap();
+                (slug, input_path)
+            })
+            .collect::<Vec<_>>();
         build_nav(&entries, &args[2])
     } else if args.len() == 6 && &args[1] == "build-page" {
         build_page(&args[2], &args[3], &args[4], &args[5])
@@ -42,10 +45,13 @@ fn build_nav(entries: &[(&str, &str)], nav_path: &str) -> Result<(), Box<dyn Err
     let arena = Arena::new();
     let options = comrak_options();
 
-    let nav = entries.iter().map(|&(slug, input_path)| {
-        let title = load_page_title(&arena, &options, input_path)?;
-        Ok((slug, title))
-    }).collect::<io::Result<Vec<_>>>()?;
+    let nav = entries
+        .iter()
+        .map(|&(slug, input_path)| {
+            let title = load_page_title(&arena, &options, input_path)?;
+            Ok((slug, title))
+        })
+        .collect::<io::Result<Vec<_>>>()?;
 
     // Only write if different to avoid spurious rebuilds
     let old_string = fs::read_to_string(nav_path).unwrap_or(String::new());
@@ -73,12 +79,15 @@ fn build_page(
     let arena = Arena::new();
     let options = comrak_options();
 
-    let nav = nav.iter().filter_map(|(slug, title)| {
-        title.as_ref().map(|title| {
-            let title = comrak::parse_document(&arena, title, &options);
-            (slug.as_str(), title)
+    let nav = nav
+        .iter()
+        .filter_map(|(slug, title)| {
+            title.as_ref().map(|title| {
+                let title = comrak::parse_document(&arena, title, &options);
+                (slug.as_str(), title)
+            })
         })
-    }).collect::<Vec<_>>();
+        .collect::<Vec<_>>();
 
     let page = load_page(&arena, &options, input_path)?;
     let markup = views::main(&options, slug, page, &nav);
@@ -99,8 +108,7 @@ fn load_page<'a>(
     lower_headings(page.content);
     rewrite_md_links(page.content)
         .map_err(|err| io::Error::new(io::ErrorKind::InvalidData, err))?;
-    highlight_code(page.content)
-        .map_err(|err| io::Error::new(io::ErrorKind::InvalidData, err))?;
+    highlight_code(page.content).map_err(|err| io::Error::new(io::ErrorKind::InvalidData, err))?;
 
     Ok(page)
 }
@@ -113,11 +121,7 @@ fn load_page_title<'a>(
     let page = load_page_raw(arena, options, path)?;
     let title = page.title.map(|title| {
         let mut buffer = String::new();
-        comrak::format_commonmark(
-            title,
-            options,
-            &mut StringWriter(&mut buffer),
-        ).unwrap();
+        comrak::format_commonmark(title, options, &mut StringWriter(&mut buffer)).unwrap();
         buffer
     });
     Ok(title)
@@ -131,18 +135,16 @@ fn load_page_raw<'a>(
     let buffer = fs::read_to_string(path)?;
     let content = comrak::parse_document(arena, &buffer, options);
 
-    let title = content
-        .first_child()
-        .filter(|node| {
-            let mut data = node.data.borrow_mut();
-            if let NodeValue::Heading(NodeHeading { level: 1, .. }) = data.value {
-                node.detach();
-                data.value = NodeValue::Document;
-                true
-            } else {
-                false
-            }
-        });
+    let title = content.first_child().filter(|node| {
+        let mut data = node.data.borrow_mut();
+        if let NodeValue::Heading(NodeHeading { level: 1, .. }) = data.value {
+            node.detach();
+            data.value = NodeValue::Document;
+            true
+        } else {
+            false
+        }
+    });
 
     Ok(Page { title, content })
 }
@@ -175,12 +177,18 @@ fn highlight_code<'a>(root: &'a AstNode<'a>) -> Result<(), FromUtf8Error> {
     let ss = SyntaxSet::load_defaults_newlines();
     let ts = ThemeSet::load_defaults();
     let mut theme = ts.themes["InspiredGitHub"].clone();
-    theme.settings.background = Some(Color { r: 0xff, g: 0xee, b: 0xff, a: 0xff });
+    theme.settings.background = Some(Color {
+        r: 0xff,
+        g: 0xee,
+        b: 0xff,
+        a: 0xff,
+    });
     for node in root.descendants() {
         let mut data = node.data.borrow_mut();
-        if let NodeValue::CodeBlock(NodeCodeBlock { info, literal, ..  }) = &mut data.value {
+        if let NodeValue::CodeBlock(NodeCodeBlock { info, literal, .. }) = &mut data.value {
             let info = String::from_utf8(mem::replace(info, Vec::new()))?;
-            let syntax = ss.find_syntax_by_token(&info)
+            let syntax = ss
+                .find_syntax_by_token(&info)
                 .unwrap_or_else(|| ss.find_syntax_plain_text());
             let mut literal = String::from_utf8(mem::replace(literal, Vec::new()))?;
             if !literal.ends_with('\n') {
diff --git a/docs/src/page.rs b/docs/src/page.rs
index 7f5a6c5..42e9bc0 100644
--- a/docs/src/page.rs
+++ b/docs/src/page.rs
@@ -4,4 +4,3 @@ pub struct Page<'a> {
     pub title: Option<&'a AstNode<'a>>,
     pub content: &'a AstNode<'a>,
 }
-
diff --git a/docs/src/views.rs b/docs/src/views.rs
index 06e0c84..43cae7f 100644
--- a/docs/src/views.rs
+++ b/docs/src/views.rs
@@ -1,8 +1,8 @@
-use comrak::{self, ComrakOptions};
-use comrak::nodes::AstNode;
-use crate::Page;
 use crate::string_writer::StringWriter;
-use maud::{DOCTYPE, Markup, PreEscaped, Render, html};
+use crate::Page;
+use comrak::nodes::AstNode;
+use comrak::{self, ComrakOptions};
+use maud::{html, Markup, PreEscaped, Render, DOCTYPE};
 use std::str;
 
 struct Comrak<'a>(&'a AstNode<'a>, &'a ComrakOptions);
@@ -22,7 +22,12 @@ impl<'a> Render for ComrakRemovePTags<'a> {
         let mut buffer = String::new();
         comrak::format_html(self.0, self.1, &mut StringWriter(&mut buffer)).unwrap();
         assert!(buffer.starts_with("<p>") && buffer.ends_with("</p>\n"));
-        PreEscaped(buffer.trim_start_matches("<p>").trim_end_matches("</p>\n").to_string())
+        PreEscaped(
+            buffer
+                .trim_start_matches("<p>")
+                .trim_end_matches("</p>\n")
+                .to_string(),
+        )
     }
 }
 
diff --git a/maud/src/lib.rs b/maud/src/lib.rs
index 02e1386..8d6b153 100644
--- a/maud/src/lib.rs
+++ b/maud/src/lib.rs
@@ -9,9 +9,12 @@
 
 #![doc(html_root_url = "https://docs.rs/maud/0.22.0")]
 
-#[cfg(feature = "actix-web")] extern crate actix_web_dep;
-#[cfg(feature = "iron")] extern crate iron;
-#[cfg(feature = "rocket")] extern crate rocket;
+#[cfg(feature = "actix-web")]
+extern crate actix_web_dep;
+#[cfg(feature = "iron")]
+extern crate iron;
+#[cfg(feature = "rocket")]
+extern crate rocket;
 
 use std::fmt::{self, Write};
 
@@ -161,12 +164,12 @@ pub const DOCTYPE: PreEscaped<&'static str> = PreEscaped("<!DOCTYPE html>");
 
 #[cfg(feature = "iron")]
 mod iron_support {
-    use std::io;
+    use crate::PreEscaped;
     use iron::headers::ContentType;
     use iron::modifier::{Modifier, Set};
     use iron::modifiers::Header;
     use iron::response::{Response, WriteBody};
-    use crate::PreEscaped;
+    use std::io;
 
     impl Modifier<Response> for PreEscaped<String> {
         fn modify(self, response: &mut Response) {
@@ -185,11 +188,11 @@ mod iron_support {
 
 #[cfg(feature = "rocket")]
 mod rocket_support {
+    use crate::PreEscaped;
     use rocket::http::{ContentType, Status};
     use rocket::request::Request;
     use rocket::response::{Responder, Response};
     use std::io::Cursor;
-    use crate::PreEscaped;
 
     impl Responder<'static> for PreEscaped<String> {
         fn respond_to(self, _: &Request) -> Result<Response<'static>, Status> {
@@ -204,7 +207,7 @@ mod rocket_support {
 #[cfg(feature = "actix-web")]
 mod actix_support {
     use crate::PreEscaped;
-    use actix_web_dep::{Responder, HttpResponse, HttpRequest, Error};
+    use actix_web_dep::{Error, HttpRequest, HttpResponse, Responder};
     use futures::future::{ok, Ready};
 
     impl Responder for PreEscaped<String> {
@@ -212,8 +215,8 @@ mod actix_support {
         type Future = Ready<Result<HttpResponse, Self::Error>>;
         fn respond_to(self, _req: &HttpRequest) -> Self::Future {
             ok(HttpResponse::Ok()
-               .content_type("text/html; charset=utf-8")
-               .body(self.0))
+                .content_type("text/html; charset=utf-8")
+                .body(self.0))
         }
     }
 }
diff --git a/maud/tests/absolute_paths.rs b/maud/tests/absolute_paths.rs
index baee0b3..690af2e 100644
--- a/maud/tests/absolute_paths.rs
+++ b/maud/tests/absolute_paths.rs
@@ -1,5 +1,4 @@
 #![feature(proc_macro_hygiene)]
-
 // Make sure `std` is available but the prelude isn't
 #![no_std]
 extern crate std;
diff --git a/maud/tests/basic_syntax.rs b/maud/tests/basic_syntax.rs
index 42aafb9..94dc510 100644
--- a/maud/tests/basic_syntax.rs
+++ b/maud/tests/basic_syntax.rs
@@ -1,6 +1,6 @@
 #![feature(proc_macro_hygiene)]
 
-use maud::{Markup, html};
+use maud::{html, Markup};
 
 #[test]
 fn literals() {
@@ -22,7 +22,8 @@ fn semicolons() {
         "three";
         ;;;;;;;;;;;;;;;;;;;;;;;;
         "four";
-    }.into_string();
+    }
+    .into_string();
     assert_eq!(s, "onetwothreefour");
 }
 
@@ -34,7 +35,8 @@ fn blocks() {
             " ducks" " geese"
         }
         " swans"
-    }.into_string();
+    }
+    .into_string();
     assert_eq!(s, "hello ducks geese swans");
 }
 
@@ -63,10 +65,15 @@ fn simple_attributes() {
         section id="midriff" {
             p class="hotpink" { "Hello!" }
         }
-    }.into_string();
-    assert_eq!(s, concat!(
+    }
+    .into_string();
+    assert_eq!(
+        s,
+        concat!(
             r#"<link rel="stylesheet" href="styles.css">"#,
-            r#"<section id="midriff"><p class="hotpink">Hello!</p></section>"#));
+            r#"<section id="midriff"><p class="hotpink">Hello!</p></section>"#
+        )
+    );
 }
 
 #[test]
@@ -83,17 +90,24 @@ fn toggle_empty_attributes() {
         input checked?[false];
         input checked?[rocks];
         input checked?[!rocks];
-    }).into_string();
-    assert_eq!(s, concat!(
+    })
+    .into_string();
+    assert_eq!(
+        s,
+        concat!(
             r#"<input checked>"#,
             r#"<input>"#,
             r#"<input checked>"#,
-            r#"<input>"#));
+            r#"<input>"#
+        )
+    );
 }
 
 #[test]
 fn toggle_empty_attributes_braces() {
-    struct Maud { rocks: bool }
+    struct Maud {
+        rocks: bool,
+    }
     let s = html!(input checked?[Maud { rocks: true }.rocks] /).into_string();
     assert_eq!(s, r#"<input checked>"#);
 }
@@ -101,10 +115,14 @@ fn toggle_empty_attributes_braces() {
 #[test]
 fn colons_in_names() {
     let s = html!(pon-pon:controls-alpha { a on:click="yay()" { "Yay!" } }).into_string();
-    assert_eq!(s, concat!(
+    assert_eq!(
+        s,
+        concat!(
             r#"<pon-pon:controls-alpha>"#,
             r#"<a on:click="yay()">Yay!</a>"#,
-            r#"</pon-pon:controls-alpha>"#));
+            r#"</pon-pon:controls-alpha>"#
+        )
+    );
 }
 
 #[rustfmt::skip::macros(html)]
@@ -155,15 +173,29 @@ fn toggle_classes() {
     fn test(is_cupcake: bool, is_muffin: bool) -> Markup {
         html!(p.cupcake[is_cupcake].muffin[is_muffin] { "Testing!" })
     }
-    assert_eq!(test(true, true).into_string(), r#"<p class="cupcake muffin">Testing!</p>"#);
-    assert_eq!(test(false, true).into_string(), r#"<p class=" muffin">Testing!</p>"#);
-    assert_eq!(test(true, false).into_string(), r#"<p class="cupcake">Testing!</p>"#);
-    assert_eq!(test(false, false).into_string(), r#"<p class="">Testing!</p>"#);
+    assert_eq!(
+        test(true, true).into_string(),
+        r#"<p class="cupcake muffin">Testing!</p>"#
+    );
+    assert_eq!(
+        test(false, true).into_string(),
+        r#"<p class=" muffin">Testing!</p>"#
+    );
+    assert_eq!(
+        test(true, false).into_string(),
+        r#"<p class="cupcake">Testing!</p>"#
+    );
+    assert_eq!(
+        test(false, false).into_string(),
+        r#"<p class="">Testing!</p>"#
+    );
 }
 
 #[test]
 fn toggle_classes_braces() {
-    struct Maud { rocks: bool }
+    struct Maud {
+        rocks: bool,
+    }
     let s = html!(p.rocks[Maud { rocks: true }.rocks] { "Awesome!" }).into_string();
     assert_eq!(s, r#"<p class="rocks">Awesome!</p>"#);
 }
@@ -181,8 +213,14 @@ fn mixed_classes() {
     fn test(is_muffin: bool) -> Markup {
         html!(p.cupcake.muffin[is_muffin].lamington { "Testing!" })
     }
-    assert_eq!(test(true).into_string(), r#"<p class="cupcake lamington muffin">Testing!</p>"#);
-    assert_eq!(test(false).into_string(), r#"<p class="cupcake lamington">Testing!</p>"#);
+    assert_eq!(
+        test(true).into_string(),
+        r#"<p class="cupcake lamington muffin">Testing!</p>"#
+    );
+    assert_eq!(
+        test(false).into_string(),
+        r#"<p class="cupcake lamington">Testing!</p>"#
+    );
 }
 
 #[test]
@@ -200,7 +238,10 @@ fn id_string() {
 #[test]
 fn classes_attrs_ids_mixed_up() {
     let s = html!(p { "Hi, " span.name.here lang="en" #thing { "Lyra" } "!" }).into_string();
-    assert_eq!(s, r#"<p>Hi, <span class="name here" id="thing" lang="en">Lyra</span>!</p>"#);
+    assert_eq!(
+        s,
+        r#"<p>Hi, <span class="name here" id="thing" lang="en">Lyra</span>!</p>"#
+    );
 }
 
 #[test]
@@ -218,11 +259,17 @@ fn div_shorthand_id() {
 #[test]
 fn div_shorthand_class_with_attrs() {
     let s = html!(.awesome-class contenteditable? dir="rtl" #unique-id {}).into_string();
-    assert_eq!(s, r#"<div class="awesome-class" id="unique-id" contenteditable dir="rtl"></div>"#);
+    assert_eq!(
+        s,
+        r#"<div class="awesome-class" id="unique-id" contenteditable dir="rtl"></div>"#
+    );
 }
 
 #[test]
 fn div_shorthand_id_with_attrs() {
     let s = html!(#unique-id contenteditable? dir="rtl" .awesome-class {}).into_string();
-    assert_eq!(s, r#"<div class="awesome-class" id="unique-id" contenteditable dir="rtl"></div>"#);
+    assert_eq!(
+        s,
+        r#"<div class="awesome-class" id="unique-id" contenteditable dir="rtl"></div>"#
+    );
 }
diff --git a/maud/tests/control_structures.rs b/maud/tests/control_structures.rs
index b4b07ba..18cf2fa 100644
--- a/maud/tests/control_structures.rs
+++ b/maud/tests/control_structures.rs
@@ -15,7 +15,8 @@ fn if_expr() {
             } @else {
                 "oh noes"
             }
-        }.into_string();
+        }
+        .into_string();
         assert_eq!(s, name);
     }
 }
@@ -25,13 +26,13 @@ fn if_expr_in_class() {
     for &(chocolate_milk, expected) in &[
         (0, r#"<p class="empty">Chocolate milk</p>"#),
         (1, r#"<p class="full">Chocolate milk</p>"#),
-    ]
-    {
+    ] {
         let s = html! {
             p.@if chocolate_milk == 0 { "empty" } @else { "full" } {
                 "Chocolate milk"
             }
-        }.into_string();
+        }
+        .into_string();
         assert_eq!(s, expected);
     }
 }
@@ -45,7 +46,8 @@ fn if_let() {
             } @else {
                 "oh noes"
             }
-        }.into_string();
+        }
+        .into_string();
         assert_eq!(s, output);
     }
 }
@@ -59,7 +61,8 @@ fn while_expr() {
                 li { (numbers.next().unwrap()) }
             }
         }
-    }.into_string();
+    }
+    .into_string();
     assert_eq!(s, "<ul><li>0</li><li>1</li><li>2</li></ul>");
 }
 
@@ -72,7 +75,8 @@ fn while_let_expr() {
                 li { (n) }
             }
         }
-    }.into_string();
+    }
+    .into_string();
     assert_eq!(s, "<ul><li>0</li><li>1</li><li>2</li></ul>");
 }
 
@@ -85,13 +89,18 @@ fn for_expr() {
                 li { (pony) }
             }
         }
-    }.into_string();
-    assert_eq!(s, concat!(
+    }
+    .into_string();
+    assert_eq!(
+        s,
+        concat!(
             "<ul>",
             "<li>Apple Bloom</li>",
             "<li>Scootaloo</li>",
             "<li>Sweetie Belle</li>",
-            "</ul>"));
+            "</ul>"
+        )
+    );
 }
 
 #[test]
@@ -106,7 +115,8 @@ fn match_expr() {
                     "oh noes"
                 },
             }
-        }.into_string();
+        }
+        .into_string();
         assert_eq!(s, output);
     }
 }
@@ -119,7 +129,8 @@ fn match_expr_without_delims() {
                 Some(value) => (value),
                 None => span { "oh noes" },
             }
-        }.into_string();
+        }
+        .into_string();
         assert_eq!(s, output);
     }
 }
@@ -132,7 +143,8 @@ fn match_no_trailing_comma() {
                 Some(value) => { (value) }
                 None => span { "oh noes" }
             }
-        }.into_string();
+        }
+        .into_string();
         assert_eq!(s, output);
     }
 }
@@ -146,21 +158,27 @@ fn match_expr_with_guards() {
                 Some(value) => (value),
                 None => "none",
             }
-        }.into_string();
+        }
+        .into_string();
         assert_eq!(s, output);
     }
 }
 
 #[test]
 fn match_in_attribute() {
-    for &(input, output) in &[(1, "<span class=\"one\">1</span>"), (2, "<span class=\"two\">2</span>"), (3, "<span class=\"many\">3</span>")] {
+    for &(input, output) in &[
+        (1, "<span class=\"one\">1</span>"),
+        (2, "<span class=\"two\">2</span>"),
+        (3, "<span class=\"many\">3</span>"),
+    ] {
         let s = html! {
             span class=@match input {
                 1 => "one",
                 2 => "two",
                 _ => "many",
             } { (input) }
-        }.into_string();
+        }
+        .into_string();
         assert_eq!(s, output);
     }
 }
@@ -170,7 +188,8 @@ fn let_expr() {
     let s = html! {
         @let x = 42;
         "I have " (x) " cupcakes!"
-    }.into_string();
+    }
+    .into_string();
     assert_eq!(s, "I have 42 cupcakes!");
 }
 
@@ -183,10 +202,12 @@ fn let_lexical_scope() {
             "Twilight thought I had " (x) " cupcakes, "
         }
         "but I only had " (x) "."
-    }.into_string();
-    assert_eq!(s, concat!(
-            "Twilight thought I had 99 cupcakes, ",
-            "but I only had 42."));
+    }
+    .into_string();
+    assert_eq!(
+        s,
+        concat!("Twilight thought I had 99 cupcakes, ", "but I only had 42.")
+    );
 }
 
 #[test]
@@ -194,6 +215,7 @@ fn let_type_ascription() {
     let s = html! {
         @let mut x: Box<dyn Iterator<Item=u32>> = Box::new(vec![42].into_iter());
         "I have " (x.next().unwrap()) " cupcakes!"
-    }.into_string();
+    }
+    .into_string();
     assert_eq!(s, "I have 42 cupcakes!");
 }
diff --git a/maud/tests/splices.rs b/maud/tests/splices.rs
index 2b59334..9d256a2 100644
--- a/maud/tests/splices.rs
+++ b/maud/tests/splices.rs
@@ -25,7 +25,8 @@ fn blocks() {
             }
             result
         })
-    }).into_string();
+    })
+    .into_string();
     assert_eq!(s, "3628800");
 }
 
@@ -95,7 +96,8 @@ fn structs() {
     };
     let s = html!({
         "Name: " (pinkie.name) ". Rating: " (pinkie.repugnance())
-    }).into_string();
+    })
+    .into_string();
     assert_eq!(s, "Name: Pinkie Pie. Rating: 1");
 }
 
diff --git a/maud_htmlescape/lib.rs b/maud_htmlescape/lib.rs
index 5ab8535..c682c06 100644
--- a/maud_htmlescape/lib.rs
+++ b/maud_htmlescape/lib.rs
@@ -56,8 +56,8 @@ impl<'a> fmt::Write for Escaper<'a> {
 
 #[cfg(test)]
 mod test {
-    use std::fmt::Write;
     use crate::Escaper;
+    use std::fmt::Write;
 
     #[test]
     fn it_works() {
diff --git a/maud_macros/src/ast.rs b/maud_macros/src/ast.rs
index c437a1d..473f8b9 100644
--- a/maud_macros/src/ast.rs
+++ b/maud_macros/src/ast.rs
@@ -42,19 +42,20 @@ impl Markup {
             Markup::Literal { span, .. } => span,
             Markup::Symbol { ref symbol } => span_tokens(symbol.clone()),
             Markup::Splice { outer_span, .. } => outer_span,
-            Markup::Element { ref name, ref body, .. } => {
+            Markup::Element {
+                ref name, ref body, ..
+            } => {
                 let name_span = span_tokens(name.clone());
                 name_span.join_range(body.span())
-            },
-            Markup::Let { at_span, ref tokens } => {
-                at_span.join_range(span_tokens(tokens.clone()))
-            },
-            Markup::Special { ref segments } => {
-                join_ranges(segments.iter().map(Special::span))
-            },
-            Markup::Match { at_span, arms_span, .. } => {
-                at_span.join_range(arms_span)
-            },
+            }
+            Markup::Let {
+                at_span,
+                ref tokens,
+            } => at_span.join_range(span_tokens(tokens.clone())),
+            Markup::Special { ref segments } => join_ranges(segments.iter().map(Special::span)),
+            Markup::Match {
+                at_span, arms_span, ..
+            } => at_span.join_range(arms_span),
         }
     }
 }
@@ -80,7 +81,11 @@ pub enum Attr {
 impl Attr {
     pub fn span(&self) -> SpanRange {
         match *self {
-            Attr::Class { dot_span, ref name, ref toggler } => {
+            Attr::Class {
+                dot_span,
+                ref name,
+                ref toggler,
+            } => {
                 let name_span = name.span();
                 let dot_name_span = dot_span.join_range(name_span);
                 if let Some(toggler) = toggler {
@@ -88,11 +93,14 @@ impl Attr {
                 } else {
                     dot_name_span
                 }
-            },
-            Attr::Id { hash_span, ref name } => {
+            }
+            Attr::Id {
+                hash_span,
+                ref name,
+            } => {
                 let name_span = name.span();
                 hash_span.join_range(name_span)
-            },
+            }
             Attr::Attribute { ref attribute } => attribute.span(),
         }
     }
@@ -158,12 +166,8 @@ impl Attribute {
 
 #[derive(Debug)]
 pub enum AttrType {
-    Normal {
-        value: Markup,
-    },
-    Empty {
-        toggler: Option<Toggler>,
-    },
+    Normal { value: Markup },
+    Empty { toggler: Option<Toggler> },
 }
 
 impl AttrType {
@@ -193,11 +197,11 @@ pub struct MatchArm {
     pub body: Block,
 }
 
-pub fn span_tokens<I: IntoIterator<Item=TokenTree>>(tokens: I) -> SpanRange {
+pub fn span_tokens<I: IntoIterator<Item = TokenTree>>(tokens: I) -> SpanRange {
     join_ranges(tokens.into_iter().map(|s| SpanRange::single_span(s.span())))
 }
 
-pub fn join_ranges<I: IntoIterator<Item=SpanRange>>(ranges: I) -> SpanRange {
+pub fn join_ranges<I: IntoIterator<Item = SpanRange>>(ranges: I) -> SpanRange {
     let mut iter = ranges.into_iter();
     let first = match iter.next() {
         Some(span) => span,
diff --git a/maud_macros/src/generate.rs b/maud_macros/src/generate.rs
index 357896e..976ad98 100644
--- a/maud_macros/src/generate.rs
+++ b/maud_macros/src/generate.rs
@@ -1,15 +1,7 @@
 use maud_htmlescape::Escaper;
-use proc_macro2::{
-    Delimiter,
-    Group,
-    Literal,
-    Span,
-    Ident,
-    TokenStream,
-    TokenTree,
-};
-use quote::quote;
+use proc_macro2::{Delimiter, Group, Ident, Literal, Span, TokenStream, TokenTree};
 use proc_macro_error::SpanRange;
+use quote::quote;
 
 use crate::ast::*;
 
@@ -40,13 +32,22 @@ impl Generator {
 
     fn markup(&self, markup: Markup, build: &mut Builder) {
         match markup {
-            Markup::Block(Block { markups, outer_span }) => {
-                if markups.iter().any(|markup| matches!(*markup, Markup::Let { .. })) {
-                    build.push_tokens(self.block(Block { markups, outer_span }));
+            Markup::Block(Block {
+                markups,
+                outer_span,
+            }) => {
+                if markups
+                    .iter()
+                    .any(|markup| matches!(*markup, Markup::Let { .. }))
+                {
+                    build.push_tokens(self.block(Block {
+                        markups,
+                        outer_span,
+                    }));
                 } else {
                     self.markups(markups, build);
                 }
-            },
+            }
             Markup::Literal { content, .. } => build.push_escaped(&content),
             Markup::Symbol { symbol } => self.name(symbol, build),
             Markup::Splice { expr, .. } => build.push_tokens(self.splice(expr)),
@@ -56,22 +57,30 @@ impl Generator {
                 for segment in segments {
                     build.push_tokens(self.special(segment));
                 }
-            },
-            Markup::Match { head, arms, arms_span, .. } => {
+            }
+            Markup::Match {
+                head,
+                arms,
+                arms_span,
+                ..
+            } => {
                 build.push_tokens({
-                    let body = arms
-                        .into_iter()
-                        .map(|arm| self.match_arm(arm))
-                        .collect();
+                    let body = arms.into_iter().map(|arm| self.match_arm(arm)).collect();
                     let mut body = TokenTree::Group(Group::new(Delimiter::Brace, body));
                     body.set_span(arms_span.collapse());
                     quote!(#head #body)
                 });
-            },
+            }
         }
     }
 
-    fn block(&self, Block { markups, outer_span }: Block) -> TokenStream {
+    fn block(
+        &self,
+        Block {
+            markups,
+            outer_span,
+        }: Block,
+    ) -> TokenStream {
         let mut build = self.builder();
         self.markups(markups, &mut build);
         let mut block = TokenTree::Group(Group::new(Delimiter::Brace, build.finish()));
@@ -93,13 +102,7 @@ impl Generator {
         })
     }
 
-    fn element(
-        &self,
-        name: TokenStream,
-        attrs: Attrs,
-        body: ElementBody,
-        build: &mut Builder,
-    ) {
+    fn element(&self, name: TokenStream, attrs: Attrs, body: ElementBody, build: &mut Builder) {
         build.push_str("<");
         self.name(name.clone(), build);
         self.attrs(attrs, build);
@@ -113,7 +116,10 @@ impl Generator {
     }
 
     fn name(&self, name: TokenStream, build: &mut Builder) {
-        let string = name.into_iter().map(|token| token.to_string()).collect::<String>();
+        let string = name
+            .into_iter()
+            .map(|token| token.to_string())
+            .collect::<String>();
         build.push_escaped(&string);
     }
 
@@ -126,12 +132,14 @@ impl Generator {
                     build.push_str("=\"");
                     self.markup(value, build);
                     build.push_str("\"");
-                },
+                }
                 AttrType::Empty { toggler: None } => {
                     build.push_str(" ");
                     self.name(name, build);
-                },
-                AttrType::Empty { toggler: Some(toggler) } => {
+                }
+                AttrType::Empty {
+                    toggler: Some(toggler),
+                } => {
                     let head = desugar_toggler(toggler);
                     build.push_tokens({
                         let mut build = self.builder();
@@ -140,7 +148,7 @@ impl Generator {
                         let body = build.finish();
                         quote!(#head { #body })
                     })
-                },
+                }
             }
         }
     }
@@ -171,7 +179,7 @@ fn desugar_attrs(attrs: Attrs) -> Vec<Attribute> {
                 } else {
                     classes_static.push(name);
                 }
-            },
+            }
             Attr::Id { name, .. } => ids.push(name),
             Attr::Attribute { attribute } => attributes.push(attribute),
         }
@@ -201,7 +209,11 @@ fn desugar_classes_or_ids(
         };
         let head = desugar_toggler(toggler);
         markups.push(Markup::Special {
-            segments: vec![Special { at_span: SpanRange::call_site(), head, body }],
+            segments: vec![Special {
+                at_span: SpanRange::call_site(),
+                head,
+                body,
+            }],
         });
     }
     Some(Attribute {
@@ -228,7 +240,12 @@ fn prepend_leading_space(name: Markup, leading_space: &mut bool) -> Vec<Markup>
     markups
 }
 
-fn desugar_toggler(Toggler { mut cond, cond_span }: Toggler) -> TokenStream {
+fn desugar_toggler(
+    Toggler {
+        mut cond,
+        cond_span,
+    }: Toggler,
+) -> TokenStream {
     // If the expression contains an opening brace `{`,
     // wrap it in parentheses to avoid parse errors
     if cond.clone().into_iter().any(is_braced_block) {
diff --git a/maud_macros/src/lib.rs b/maud_macros/src/lib.rs
index dd63725..a142516 100644
--- a/maud_macros/src/lib.rs
+++ b/maud_macros/src/lib.rs
@@ -1,7 +1,5 @@
 #![feature(proc_macro_hygiene)]
-
 #![doc(html_root_url = "https://docs.rs/maud_macros/0.22.0")]
-
 // TokenStream values are reference counted, and the mental overhead of tracking
 // lifetimes outweighs the marginal gains from explicit borrowing
 #![allow(clippy::needless_pass_by_value)]
@@ -13,8 +11,8 @@ mod generate;
 mod parse;
 
 use proc_macro2::{Ident, TokenStream, TokenTree};
+use proc_macro_error::proc_macro_error;
 use quote::quote;
-use proc_macro_error::{proc_macro_error};
 
 #[proc_macro]
 #[proc_macro_error]
@@ -32,7 +30,10 @@ pub fn html_debug(input: proc_macro::TokenStream) -> proc_macro::TokenStream {
 
 fn expand(input: TokenStream) -> TokenStream {
     // TODO: call `proc_macro2::Span::mixed_site()` directly when Rust 1.45 is stable
-    let output_ident = TokenTree::Ident(Ident::new("__maud_output", proc_macro::Span::mixed_site().into()));
+    let output_ident = TokenTree::Ident(Ident::new(
+        "__maud_output",
+        proc_macro::Span::mixed_site().into(),
+    ));
     // Heuristic: the size of the resulting markup tends to correlate with the
     // code size of the template itself
     let size_hint = input.to_string().len();
diff --git a/maud_macros/src/parse.rs b/maud_macros/src/parse.rs
index e0b35ff..6390969 100644
--- a/maud_macros/src/parse.rs
+++ b/maud_macros/src/parse.rs
@@ -1,17 +1,9 @@
-use proc_macro2::{
-    Delimiter,
-    Ident,
-    Literal,
-    Spacing,
-    Span,
-    TokenStream,
-    TokenTree,
-};
+use proc_macro2::{Delimiter, Ident, Literal, Spacing, Span, TokenStream, TokenTree};
 use proc_macro_error::{abort, abort_call_site, SpanRange};
 use std::collections::HashMap;
 use std::mem;
 
-use syn::{LitStr, parse_str};
+use syn::{parse_str, LitStr};
 
 use crate::ast;
 
@@ -83,14 +75,13 @@ impl Parser {
             match self.peek2() {
                 None => break,
                 Some((TokenTree::Punct(ref punct), _)) if punct.as_char() == ';' => self.advance(),
-                Some((
-                    TokenTree::Punct(ref punct),
-                    Some(TokenTree::Ident(ref ident)),
-                )) if punct.as_char() == '@' && *ident == "let" => {
+                Some((TokenTree::Punct(ref punct), Some(TokenTree::Ident(ref ident))))
+                    if punct.as_char() == '@' && *ident == "let" =>
+                {
                     self.advance2();
                     let keyword = TokenTree::Ident(ident.clone());
                     result.push(self.let_expr(punct.span(), keyword));
-                },
+                }
                 _ => result.push(self.markup()),
             }
         }
@@ -103,14 +94,14 @@ impl Parser {
             Some(token) => token,
             None => {
                 abort_call_site!("unexpected end of input");
-            },
+            }
         };
         let markup = match token {
             // Literal
             TokenTree::Literal(lit) => {
                 self.advance();
                 self.literal(&lit)
-            },
+            }
             // Special form
             TokenTree::Punct(ref punct) if punct.as_char() == '@' => {
                 self.advance();
@@ -123,25 +114,31 @@ impl Parser {
                                 let mut segments = Vec::new();
                                 self.if_expr(at_span, vec![keyword], &mut segments);
                                 ast::Markup::Special { segments }
-                            },
+                            }
                             "while" => self.while_expr(at_span, keyword),
                             "for" => self.for_expr(at_span, keyword),
                             "match" => self.match_expr(at_span, keyword),
                             "let" => {
-                                let span = SpanRange { first: at_span, last: ident.span() };
+                                let span = SpanRange {
+                                    first: at_span,
+                                    last: ident.span(),
+                                };
                                 abort!(span, "`@let` only works inside a block");
-                            },
+                            }
                             other => {
-                                let span = SpanRange { first: at_span, last: ident.span() };
+                                let span = SpanRange {
+                                    first: at_span,
+                                    last: ident.span(),
+                                };
                                 abort!(span, "unknown keyword `@{}`", other);
                             }
                         }
-                    },
+                    }
                     _ => {
                         abort!(at_span, "expected keyword after `@`");
-                    },
+                    }
                 }
-            },
+            }
             // Element
             TokenTree::Ident(ident) => {
                 let ident_string = ident.to_string();
@@ -161,26 +158,29 @@ impl Parser {
                 // already seen an `Ident`
                 let name = self.try_namespaced_name().expect("identifier");
                 self.element(name)
-            },
+            }
             // Div element shorthand
             TokenTree::Punct(ref punct) if punct.as_char() == '.' || punct.as_char() == '#' => {
                 let name = TokenTree::Ident(Ident::new("div", punct.span()));
                 self.element(name.into())
-            },
+            }
             // Splice
             TokenTree::Group(ref group) if group.delimiter() == Delimiter::Parenthesis => {
                 self.advance();
-                ast::Markup::Splice { expr: group.stream(), outer_span: SpanRange::single_span(group.span()) }
+                ast::Markup::Splice {
+                    expr: group.stream(),
+                    outer_span: SpanRange::single_span(group.span()),
+                }
             }
             // Block
             TokenTree::Group(ref group) if group.delimiter() == Delimiter::Brace => {
                 self.advance();
                 ast::Markup::Block(self.block(group.stream(), SpanRange::single_span(group.span())))
-            },
+            }
             // ???
             token => {
                 abort!(token, "invalid syntax");
-            },
+            }
         };
         markup
     }
@@ -199,24 +199,19 @@ impl Parser {
     /// Parses an `@if` expression.
     ///
     /// The leading `@if` should already be consumed.
-    fn if_expr(
-        &mut self,
-        at_span: Span,
-        prefix: Vec<TokenTree>,
-        segments: &mut Vec<ast::Special>,
-    ) {
+    fn if_expr(&mut self, at_span: Span, prefix: Vec<TokenTree>, segments: &mut Vec<ast::Special>) {
         let mut head = prefix;
         let body = loop {
             match self.next() {
                 Some(TokenTree::Group(ref block)) if block.delimiter() == Delimiter::Brace => {
                     break self.block(block.stream(), SpanRange::single_span(block.span()));
-                },
+                }
                 Some(token) => head.push(token),
                 None => {
                     let mut span = ast::span_tokens(head);
                     span.first = at_span;
                     abort!(span, "expected body for this `@if`");
-                },
+                }
             }
         };
         segments.push(ast::Special {
@@ -232,10 +227,9 @@ impl Parser {
     /// The leading `@else if` or `@else` should *not* already be consumed.
     fn else_if_expr(&mut self, segments: &mut Vec<ast::Special>) {
         match self.peek2() {
-            Some((
-                TokenTree::Punct(ref punct),
-                Some(TokenTree::Ident(ref else_keyword)),
-            )) if punct.as_char() == '@' && *else_keyword == "else" => {
+            Some((TokenTree::Punct(ref punct), Some(TokenTree::Ident(ref else_keyword))))
+                if punct.as_char() == '@' && *else_keyword == "else" =>
+            {
                 self.advance2();
                 let at_span = punct.span();
                 let else_keyword = TokenTree::Ident(else_keyword.clone());
@@ -245,28 +239,32 @@ impl Parser {
                         self.advance();
                         let if_keyword = TokenTree::Ident(if_keyword.clone());
                         self.if_expr(at_span, vec![else_keyword, if_keyword], segments)
-                    },
+                    }
                     // Just an `@else`
-                    _ => {
-                        match self.next() {
-                            Some(TokenTree::Group(ref group)) if group.delimiter() == Delimiter::Brace => {
-                                let body = self.block(group.stream(), SpanRange::single_span(group.span()));
-                                segments.push(ast::Special {
-                                    at_span: SpanRange::single_span(at_span),
-                                    head: vec![else_keyword].into_iter().collect(),
-                                    body,
-                                });
-                            },
-                            _ => {
-                                let span = SpanRange { first: at_span, last: else_keyword.span() };
-                                abort!(span, "expected body for this `@else`");
-                            },
+                    _ => match self.next() {
+                        Some(TokenTree::Group(ref group))
+                            if group.delimiter() == Delimiter::Brace =>
+                        {
+                            let body =
+                                self.block(group.stream(), SpanRange::single_span(group.span()));
+                            segments.push(ast::Special {
+                                at_span: SpanRange::single_span(at_span),
+                                head: vec![else_keyword].into_iter().collect(),
+                                body,
+                            });
+                        }
+                        _ => {
+                            let span = SpanRange {
+                                first: at_span,
+                                last: else_keyword.span(),
+                            };
+                            abort!(span, "expected body for this `@else`");
                         }
                     },
                 }
-            },
+            }
             // We didn't find an `@else`; stop
-            _ => {},
+            _ => {}
         }
     }
 
@@ -280,16 +278,23 @@ impl Parser {
             match self.next() {
                 Some(TokenTree::Group(ref block)) if block.delimiter() == Delimiter::Brace => {
                     break self.block(block.stream(), SpanRange::single_span(block.span()));
-                },
+                }
                 Some(token) => head.push(token),
                 None => {
-                    let span = SpanRange { first: at_span, last: keyword_span };
+                    let span = SpanRange {
+                        first: at_span,
+                        last: keyword_span,
+                    };
                     abort!(span, "expected body for this `@while`");
-                },
+                }
             }
         };
         ast::Markup::Special {
-            segments: vec![ast::Special { at_span: SpanRange::single_span(at_span), head: head.into_iter().collect(), body }],
+            segments: vec![ast::Special {
+                at_span: SpanRange::single_span(at_span),
+                head: head.into_iter().collect(),
+                body,
+            }],
         }
     }
 
@@ -304,28 +309,38 @@ impl Parser {
                 Some(TokenTree::Ident(ref in_keyword)) if *in_keyword == "in" => {
                     head.push(TokenTree::Ident(in_keyword.clone()));
                     break;
-                },
+                }
                 Some(token) => head.push(token),
                 None => {
-                    let span = SpanRange { first: at_span, last: keyword_span };
+                    let span = SpanRange {
+                        first: at_span,
+                        last: keyword_span,
+                    };
                     abort!(span, "missing `in` in `@for` loop");
-                },
+                }
             }
         }
         let body = loop {
             match self.next() {
                 Some(TokenTree::Group(ref block)) if block.delimiter() == Delimiter::Brace => {
                     break self.block(block.stream(), SpanRange::single_span(block.span()));
-                },
+                }
                 Some(token) => head.push(token),
                 None => {
-                    let span = SpanRange { first: at_span, last: keyword_span };
+                    let span = SpanRange {
+                        first: at_span,
+                        last: keyword_span,
+                    };
                     abort!(span, "expected body for this `@for`");
-                },
+                }
             }
         };
         ast::Markup::Special {
-            segments: vec![ast::Special { at_span: SpanRange::single_span(at_span), head: head.into_iter().collect(), body }],
+            segments: vec![ast::Special {
+                at_span: SpanRange::single_span(at_span),
+                head: head.into_iter().collect(),
+                body,
+            }],
         }
     }
 
@@ -340,15 +355,23 @@ impl Parser {
                 Some(TokenTree::Group(ref body)) if body.delimiter() == Delimiter::Brace => {
                     let span = SpanRange::single_span(body.span());
                     break (self.with_input(body.stream()).match_arms(), span);
-                },
+                }
                 Some(token) => head.push(token),
                 None => {
-                    let span = SpanRange { first: at_span, last: keyword_span };
+                    let span = SpanRange {
+                        first: at_span,
+                        last: keyword_span,
+                    };
                     abort!(span, "expected body for this `@match`");
-                },
+                }
             }
         };
-        ast::Markup::Match { at_span: SpanRange::single_span(at_span), head: head.into_iter().collect(), arms, arms_span }
+        ast::Markup::Match {
+            at_span: SpanRange::single_span(at_span),
+            head: head.into_iter().collect(),
+            arms,
+            arms_span,
+        }
     }
 
     fn match_arms(&mut self) -> Vec<ast::MatchArm> {
@@ -364,16 +387,19 @@ impl Parser {
         loop {
             match self.peek2() {
                 Some((TokenTree::Punct(ref eq), Some(TokenTree::Punct(ref gt))))
-                if eq.as_char() == '=' && gt.as_char() == '>' && eq.spacing() == Spacing::Joint => {
+                    if eq.as_char() == '='
+                        && gt.as_char() == '>'
+                        && eq.spacing() == Spacing::Joint =>
+                {
                     self.advance2();
                     head.push(TokenTree::Punct(eq.clone()));
                     head.push(TokenTree::Punct(gt.clone()));
                     break;
-                },
+                }
                 Some((token, _)) => {
                     self.advance();
                     head.push(token);
-                },
+                }
                 None => {
                     if head.is_empty() {
                         return None;
@@ -381,7 +407,7 @@ impl Parser {
                         let head_span = ast::span_tokens(head);
                         abort!(head_span, "unexpected end of @match pattern");
                     }
-                },
+                }
             }
         }
         let body = match self.next() {
@@ -395,7 +421,7 @@ impl Parser {
                     }
                 }
                 body
-            },
+            }
             // $pat => $expr
             Some(first_token) => {
                 let mut span = SpanRange::single_span(first_token.span());
@@ -406,18 +432,21 @@ impl Parser {
                         Some(token) => {
                             span.last = token.span();
                             body.push(token);
-                        },
+                        }
                         None => break,
                     }
                 }
                 self.block(body.into_iter().collect(), span)
-            },
+            }
             None => {
                 let span = ast::span_tokens(head);
                 abort!(span, "unexpected end of @match arm");
-            },
+            }
         };
-        Some(ast::MatchArm { head: head.into_iter().collect(), body })
+        Some(ast::MatchArm {
+            head: head.into_iter().collect(),
+            body,
+        })
     }
 
     /// Parses a `@let` expression.
@@ -427,14 +456,12 @@ impl Parser {
         let mut tokens = vec![keyword];
         loop {
             match self.next() {
-                Some(token) => {
-                    match token {
-                        TokenTree::Punct(ref punct) if punct.as_char() == '=' => {
-                            tokens.push(token.clone());
-                            break;
-                        },
-                        _ => tokens.push(token),
+                Some(token) => match token {
+                    TokenTree::Punct(ref punct) if punct.as_char() == '=' => {
+                        tokens.push(token.clone());
+                        break;
                     }
+                    _ => tokens.push(token),
                 },
                 None => {
                     let mut span = ast::span_tokens(tokens);
@@ -445,14 +472,12 @@ impl Parser {
         }
         loop {
             match self.next() {
-                Some(token) => {
-                    match token {
-                        TokenTree::Punct(ref punct) if punct.as_char() == ';' => {
-                            tokens.push(token.clone());
-                            break;
-                        },
-                        _ => tokens.push(token),
+                Some(token) => match token {
+                    TokenTree::Punct(ref punct) if punct.as_char() == ';' => {
+                        tokens.push(token.clone());
+                        break;
                     }
+                    _ => tokens.push(token),
                 },
                 None => {
                     let mut span = ast::span_tokens(tokens);
@@ -462,10 +487,13 @@ impl Parser {
                         "unexpected end of `@let` expression";
                         help = "are you missing a semicolon?"
                     );
-                },
+                }
             }
         }
-        ast::Markup::Let { at_span: SpanRange::single_span(at_span), tokens: tokens.into_iter().collect() }
+        ast::Markup::Let {
+            at_span: SpanRange::single_span(at_span),
+            tokens: tokens.into_iter().collect(),
+        }
     }
 
     /// Parses an element node.
@@ -479,22 +507,23 @@ impl Parser {
         let attrs = self.attrs();
         let body = match self.peek() {
             Some(TokenTree::Punct(ref punct))
-            if punct.as_char() == ';' || punct.as_char() == '/' => {
+                if punct.as_char() == ';' || punct.as_char() == '/' =>
+            {
                 // Void element
                 self.advance();
-                ast::ElementBody::Void { semi_span: SpanRange::single_span(punct.span()) }
-            },
-            _ => {
-                match self.markup() {
-                    ast::Markup::Block(block) => ast::ElementBody::Block { block },
-                    markup => {
-                        let markup_span = markup.span();
-                        abort!(
-                            markup_span,
-                            "element body must be wrapped in braces";
-                            help = "see https://github.com/lambda-fairy/maud/pull/137 for details"
-                        );
-                    },
+                ast::ElementBody::Void {
+                    semi_span: SpanRange::single_span(punct.span()),
+                }
+            }
+            _ => match self.markup() {
+                ast::Markup::Block(block) => ast::ElementBody::Block { block },
+                markup => {
+                    let markup_span = markup.span();
+                    abort!(
+                        markup_span,
+                        "element body must be wrapped in braces";
+                        help = "see https://github.com/lambda-fairy/maud/pull/137 for details"
+                    );
                 }
             },
         };
@@ -525,7 +554,7 @@ impl Parser {
                             attr_type: ast::AttrType::Normal { value },
                         },
                     });
-                },
+                }
                 // Empty attribute
                 (Some(ref name), Some(TokenTree::Punct(ref punct))) if punct.as_char() == '?' => {
                     self.commit(attempt);
@@ -536,20 +565,27 @@ impl Parser {
                             attr_type: ast::AttrType::Empty { toggler },
                         },
                     });
-                },
+                }
                 // Class shorthand
                 (None, Some(TokenTree::Punct(ref punct))) if punct.as_char() == '.' => {
                     self.commit(attempt);
                     let name = self.class_or_id_name();
                     let toggler = self.attr_toggler();
-                    attrs.push(ast::Attr::Class { dot_span: SpanRange::single_span(punct.span()), name, toggler });
-                },
+                    attrs.push(ast::Attr::Class {
+                        dot_span: SpanRange::single_span(punct.span()),
+                        name,
+                        toggler,
+                    });
+                }
                 // ID shorthand
                 (None, Some(TokenTree::Punct(ref punct))) if punct.as_char() == '#' => {
                     self.commit(attempt);
                     let name = self.class_or_id_name();
-                    attrs.push(ast::Attr::Id { hash_span: SpanRange::single_span(punct.span()), name });
-                },
+                    attrs.push(ast::Attr::Id {
+                        hash_span: SpanRange::single_span(punct.span()),
+                        name,
+                    });
+                }
                 // If it's not a valid attribute, backtrack and bail out
                 _ => break,
             }
@@ -566,11 +602,14 @@ impl Parser {
                     }
                     has_class = true;
                     "class".to_string()
-                },
+                }
                 ast::Attr::Id { .. } => "id".to_string(),
-                ast::Attr::Attribute { attribute } => {
-                    attribute.name.clone().into_iter().map(|token| token.to_string()).collect()
-                },
+                ast::Attr::Attribute { attribute } => attribute
+                    .name
+                    .clone()
+                    .into_iter()
+                    .map(|token| token.to_string())
+                    .collect(),
             };
             let entry = attr_map.entry(name).or_default();
             entry.push(attr.span());
@@ -605,7 +644,7 @@ impl Parser {
                     cond: group.stream(),
                     cond_span: SpanRange::single_span(group.span()),
                 })
-            },
+            }
             _ => None,
         }
     }
@@ -626,12 +665,12 @@ impl Parser {
                     self.advance();
                     result.push(TokenTree::Punct(punct.clone()));
                     true
-                },
+                }
                 Some(TokenTree::Ident(ref ident)) if expect_ident => {
                     self.advance();
                     result.push(TokenTree::Ident(ident.clone()));
                     false
-                },
+                }
                 _ => break,
             };
         }
@@ -655,6 +694,9 @@ impl Parser {
     /// Parses the given token stream as a Maud expression.
     fn block(&mut self, body: TokenStream, outer_span: SpanRange) -> ast::Block {
         let markups = self.with_input(body).markups();
-        ast::Block { markups, outer_span }
+        ast::Block {
+            markups,
+            outer_span,
+        }
     }
 }