From e88d9d3179537bb369e3fa27016b0fb80bcfc5e0 Mon Sep 17 00:00:00 2001 From: Joey Hines Date: Sun, 1 Mar 2020 20:06:14 -0600 Subject: [PATCH] Added support for links in RST files + Added rst_parser.rs for future RST parsing operations + Added tests for RST parsing --- Cargo.lock | 1 + Cargo.toml | 1 + src/main.rs | 12 ++++++++--- src/rst_parser.rs | 33 +++++++++++++++++++++++++++++ src/tests/mod.rs | 13 ++++++++++++ static/raw_rst/projects/website.rst | 8 ++++--- 6 files changed, 62 insertions(+), 6 deletions(-) create mode 100644 src/rst_parser.rs create mode 100644 src/tests/mod.rs diff --git a/Cargo.lock b/Cargo.lock index 3e70410..83b20be 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -330,6 +330,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" name = "jsite" version = "0.1.0" dependencies = [ + "regex 1.3.4 (registry+https://github.com/rust-lang/crates.io-index)", "rocket 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", "rocket_contrib 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", "serde 1.0.104 (registry+https://github.com/rust-lang/crates.io-index)", diff --git a/Cargo.toml b/Cargo.toml index 89ce4f2..83463c3 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -11,6 +11,7 @@ rocket = "0.4.2" serde = "1.0" serde_derive = "1.0" serde_json = "1.0" +regex = "1.3.4" [dependencies.rocket_contrib] version = "0.4.2" diff --git a/src/main.rs b/src/main.rs index c3e1c8f..8a4431c 100644 --- a/src/main.rs +++ b/src/main.rs @@ -3,8 +3,11 @@ #[macro_use] extern crate rocket; #[macro_use] extern crate serde_derive; -use std::collections::HashMap; +mod tests; +mod rst_parser; +use rst_parser::parse_links; +use std::collections::HashMap; use rocket::Request; use rocket_contrib::templates::Template; use rocket_contrib::serve::StaticFiles; @@ -30,7 +33,6 @@ impl error::Error for PageNotFoundError { } } - #[derive(Serialize)] struct SiteFile { file_name: String, @@ -162,7 +164,7 @@ fn rst_page(page: PathBuf) -> Template { else { // Else, render the RST page let mut map = HashMap::new(); - let mut contents = match fs::read_to_string(site_page.path) { + let contents = match fs::read_to_string(site_page.path) { Ok(contents) => contents, Err(_) => { let mut map = HashMap::new(); @@ -171,6 +173,9 @@ fn rst_page(page: PathBuf) -> Template { }, }; + // Render links + let mut contents = parse_links(&contents); + // Ensure render will look good contents = contents.replace("\n", "
"); contents = contents.replace(" ", "  "); @@ -182,6 +187,7 @@ fn rst_page(page: PathBuf) -> Template { } + /// Catches 404 errors and displays an error message /// /// #Arguments diff --git a/src/rst_parser.rs b/src/rst_parser.rs new file mode 100644 index 0000000..93ef3f9 --- /dev/null +++ b/src/rst_parser.rs @@ -0,0 +1,33 @@ +use regex::Regex; +use std::collections::HashMap; + +/// Renders RST links as HTML links +/// +/// # Arguments +/// +/// * `string` - input RST string +/// +pub fn parse_links(string: & String) -> String { + let re_link_ref = Regex::new(r"\n?.. _(.*): (.*)\n").unwrap(); + let mut link_map: HashMap:: = HashMap::new(); + + for cap in re_link_ref.captures_iter(string.as_str()) { + link_map.insert(String::from(&cap[1]), String::from(&cap[2])); + } + + let mut output: String = re_link_ref.replace_all(string, "").to_string(); + + let re_link = Regex::new(r"`(.*)`_").unwrap(); + for cap in re_link.captures_iter(output.clone().as_ref()) { + let link = match link_map.get(&cap[1]) { + None => String::from(""), + Some(link) => link.to_owned() + }; + + output = output.replace(&cap[0], + format!("{}", + link, &cap[1]).as_str()); + } + + output +} diff --git a/src/tests/mod.rs b/src/tests/mod.rs new file mode 100644 index 0000000..617fca8 --- /dev/null +++ b/src/tests/mod.rs @@ -0,0 +1,13 @@ +#[cfg(test)] +use super::*; + +#[test] +fn test_link_parser() { + let mut input = String::from("This is a paragraph that contains `a link`_. + + .. _a link: https://domain.invalida\n"); + + let output = parse_links(&mut input); + + assert_eq!(output.trim_end(), "This is a paragraph that contains a link.") +} diff --git a/static/raw_rst/projects/website.rst b/static/raw_rst/projects/website.rst index e596ff9..5ba61cb 100644 --- a/static/raw_rst/projects/website.rst +++ b/static/raw_rst/projects/website.rst @@ -15,10 +15,12 @@ Picking Rust and Rocket As I am not much of a UI person, the website update was put on the back burner for sometime. The old site was "good enough." I originally considered doing it in Python and using Django. But that fails the criteria of being easily deployable. In early 2020, I began learning Rust out of curiosity and the need to use it for research. -I decided to tackle the website backend in Rust as a learning exercise. I went with the Rocket framework. It +I decided to tackle the website backend in Rust as a learning exercise. I went with the `Rocket`_ framework. It seemed to suit my needs and supported Tera templates. Tera templates are very similar to Django's templates that I had already had experience in. +.. _Rocket: https://rocket.rs/ + Easily Editable --------------- As the style of the site is a simplistic linux terminal, I decided it would be nice to have the longer pages be in @@ -40,5 +42,5 @@ improving how the site looked on mobile. Future Improvements ------------------- -As I continue to learn Rust, I plan to implement more features of RST into the raw file displays. Having clickable -links or embedding images. I want to strike a balance between the aesthetic of a terminal and ease of use of a website. \ No newline at end of file +As I continue to learn Rust, I plan to implement more features of RST into the raw file displays. For example, +embedding images. I want to strike a balance between the aesthetic of a terminal and ease of use of a website.