Static Site Generation with RDXL

Create a base webpage render function

Every webpage needs some common HTML code. This includes the HTML head preamble and any styles or scripts that you want to use on your page. Here we will use just a normal function to declare the relevant view template. Note that templates in RDXL are statically compiled rust code snippets rather than separate files read in dynamically. The approach of using macros rather than file templates creates some very unique interactions with other Rust libraries that would otherwise be unusable. This is the mix-and-match philosophy of RDXL at work.

use std::fs::File;
use std::io::prelude::*;
use rdxl::xhtml;
use rdxl_scaffolding::dom::*;

pub fn render_page(path: &str, title: String, content: String) -> std::io::Result<()> {
   let mut f = File::create(&format!("www/{}", path))?;

   f.write_all(xhtml!(
     <!Html>
       <!Meta charset="utf-8"/>
       <!Meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no"/>
       <!Title><?>{{ title }}</?></Title>
       <?>
         <div class="container">
           {{ content }}
         </div>
       </?>
     </Html>
   ).as_bytes())?;

   Ok(())
}

Write a blog post

Each individual page of the website will then use the base template. This is a common approach to website templating. RDXL is no different in this aspect. The main differentiating factor of why to use RDXL over other options is that there are no dependencies other than the procedural macros that are only defined and used at compile time. This means that the templates don't care whether they are served from Rocket or some other Rust webserver or whether the templates are being used client-side as part of a WASM application. RDXL is one of the least opinionated templating languages despite some of its more powerful abstractions.

use crate::util::render_page;
use rdxl::xhtml;

pub fn render_all() -> std::io::Result<()> {
   render_page("index.html", "My Homepage", xhtml!(
     <h1>Hey!</h1>
     <p>Hey everybody, I have a webpage now.</p>
   ))?;

   Ok(())
}

Add syntax highlighting for code snippets

What code blog would be complete without syntax highlighting. Syntect is a great module for escaping and highlighting code samples. It is also pretty simple to use for our case. In place of our html escaper function we will create a wrapper around the syntax highlighter. This function totally transforms our code samples to annotate them with information about syntax for Rust code. Other languages are also available builtin.

use syntect::html::{ClassedHTMLGenerator};
use syntect::parsing::SyntaxSet;

pub fn highlight_code(ext: &str, code_rs: &str) -> String {
   let ss = SyntaxSet::load_defaults_newlines();
   let sr_rs = ss.find_syntax_by_extension(ext).unwrap();
   let mut rs_html_generator = ClassedHTMLGenerator::new(&sr_rs, &ss);
   for line in code_rs.lines() {
      rs_html_generator.parse_html_for_line(&line);
   }
   rs_html_generator.finalize()
}