Added RST image parsing
+ Added DIP project
This commit is contained in:
+15
-16
@@ -5,9 +5,10 @@ extern crate rocket;
|
||||
#[macro_use]
|
||||
extern crate serde_derive;
|
||||
|
||||
mod rst_parser;
|
||||
mod tests;
|
||||
mod rst_parser;
|
||||
|
||||
use crate::rst_parser::parse_images;
|
||||
use regex::Regex;
|
||||
use rocket::Request;
|
||||
use rocket_contrib::serve::StaticFiles;
|
||||
@@ -16,9 +17,9 @@ use rst_parser::parse_links;
|
||||
use std::collections::HashMap;
|
||||
use std::error;
|
||||
use std::fmt;
|
||||
use std::path::{PathBuf, Path};
|
||||
use std::{fs, io};
|
||||
use std::io::Error;
|
||||
use std::path::{Path, PathBuf};
|
||||
use std::{fs, io};
|
||||
|
||||
type PageResult<T> = std::result::Result<T, JSiteError>;
|
||||
|
||||
@@ -117,7 +118,7 @@ fn get_pages(path: &str, pages: &mut Vec<SiteFile>) -> io::Result<()> {
|
||||
} else {
|
||||
match rank.parse() {
|
||||
Ok(r) => r,
|
||||
Err(_) => std::u32::MAX
|
||||
Err(_) => std::u32::MAX,
|
||||
}
|
||||
};
|
||||
|
||||
@@ -144,16 +145,15 @@ fn get_pages(path: &str, pages: &mut Vec<SiteFile>) -> io::Result<()> {
|
||||
/// * `page_name` - file to look for
|
||||
fn get_page(path: &Path) -> PageResult<SiteFile> {
|
||||
let file_name = path.file_name().ok_or(PageNotFoundError)?;
|
||||
let file_name = file_name.to_str().ok_or(PageNotFoundError)?.to_string();
|
||||
let file_name = file_name.to_str().ok_or(PageNotFoundError)?.to_string();
|
||||
if path.exists() {
|
||||
return Ok(SiteFile {
|
||||
rank: 0,
|
||||
file_name: file_name.clone(),
|
||||
link_name: file_name,
|
||||
path: path.to_path_buf()
|
||||
})
|
||||
}
|
||||
else {
|
||||
path: path.to_path_buf(),
|
||||
});
|
||||
} else {
|
||||
let mut dir_path = path.to_path_buf();
|
||||
dir_path.pop();
|
||||
|
||||
@@ -166,8 +166,8 @@ fn get_page(path: &Path) -> PageResult<SiteFile> {
|
||||
rank: 0,
|
||||
file_name: entry_name,
|
||||
link_name: file_name,
|
||||
path: entry.path()
|
||||
})
|
||||
path: entry.path(),
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -191,9 +191,7 @@ fn rst_page(page: PathBuf) -> Template {
|
||||
path.push(page);
|
||||
|
||||
// Try and get the page
|
||||
let site_page = match get_page(
|
||||
path.as_path()
|
||||
) {
|
||||
let site_page = match get_page(path.as_path()) {
|
||||
Ok(site_page) => site_page,
|
||||
Err(_) => {
|
||||
return error_page(path.to_str().unwrap());
|
||||
@@ -206,7 +204,7 @@ fn rst_page(page: PathBuf) -> Template {
|
||||
let mut sub_files: Vec<SiteFile> = Vec::new();
|
||||
match get_pages(site_page.path.to_str().unwrap(), &mut sub_files) {
|
||||
Ok(_) => (),
|
||||
Err(_) => return error_page(&site_page.link_name)
|
||||
Err(_) => return error_page(&site_page.link_name),
|
||||
}
|
||||
|
||||
let page_data = PageData {
|
||||
@@ -229,7 +227,8 @@ fn rst_page(page: PathBuf) -> Template {
|
||||
};
|
||||
|
||||
// Render links
|
||||
let mut contents = parse_links(&contents);
|
||||
let mut contents = parse_links(&contents).unwrap();
|
||||
contents = parse_images(contents.as_str()).unwrap();
|
||||
|
||||
// Ensure render will look good
|
||||
contents = contents.replace("\n", "<br>");
|
||||
|
||||
@@ -1,32 +0,0 @@
|
||||
use regex::{Regex, Captures};
|
||||
use std::collections::HashMap;
|
||||
|
||||
/// Renders RST links as HTML links
|
||||
///
|
||||
/// # Arguments
|
||||
///
|
||||
/// * `string` - input RST string
|
||||
///
|
||||
pub fn parse_links(string: &str) -> String {
|
||||
let re_link_ref = Regex::new(r"\n?.. _(.*): (.*)\n").unwrap();
|
||||
let mut link_map: HashMap<String, String> = HashMap::new();
|
||||
|
||||
for cap in re_link_ref.captures_iter(string) {
|
||||
link_map.insert(String::from(&cap[1]), String::from(&cap[2]));
|
||||
}
|
||||
|
||||
let text: String = re_link_ref.replace_all(string, "").to_string();
|
||||
|
||||
let re_link = Regex::new(r"`(.*)`_").unwrap();
|
||||
|
||||
let output = re_link.replace_all(&text, |cap: &Captures| {
|
||||
let link = match link_map.get(&cap[1]) {
|
||||
None => String::from(""),
|
||||
Some(link) => link.to_owned(),
|
||||
};
|
||||
|
||||
format!("<a class=\"link\" href=\"{}\">{}</a>", link, &cap[1])
|
||||
});
|
||||
|
||||
output.to_string()
|
||||
}
|
||||
@@ -0,0 +1,111 @@
|
||||
pub mod rst_error;
|
||||
|
||||
use regex::{Captures, Regex};
|
||||
use std::collections::HashMap;
|
||||
use rst_error::RSTError;
|
||||
use std::convert::TryFrom;
|
||||
|
||||
/// RST Image
|
||||
struct RSTImage {
|
||||
/// File location
|
||||
image_file: String,
|
||||
/// Height
|
||||
height: Option<String>,
|
||||
/// Width
|
||||
width: Option<String>,
|
||||
/// Alt Text
|
||||
alt: Option<String>,
|
||||
/// Align (not implemented)
|
||||
#[allow(dead_code)]
|
||||
align: Option<String>,
|
||||
}
|
||||
|
||||
impl RSTImage {
|
||||
/// Convert to HTML img tag
|
||||
fn to_html(&self) -> String {
|
||||
let mut html = format!("<img src=\"{}\"", self.image_file);
|
||||
let mut style = "".to_string();
|
||||
|
||||
if let Some(alt) = &self.alt {
|
||||
html = format!("{} {}", html, alt);
|
||||
}
|
||||
|
||||
if let Some(height) = &self.height {
|
||||
style = format!("{}height;{};", style, height);
|
||||
}
|
||||
if let Some(width) = &self.width {
|
||||
style = format!("{}width:{};", style, width);
|
||||
}
|
||||
|
||||
html = format!("{} style=\"{}\">", html, style);
|
||||
|
||||
html
|
||||
}
|
||||
}
|
||||
|
||||
impl TryFrom<&Captures<'_>> for RSTImage {
|
||||
type Error = RSTError;
|
||||
/// Convert from a regex capture to a RSTImage
|
||||
///
|
||||
/// # Arguments
|
||||
///
|
||||
/// * cap - regex capture
|
||||
fn try_from(cap: &Captures<'_>) -> Result<Self, Self::Error> {
|
||||
let image = Self {
|
||||
image_file: cap
|
||||
.name("file_name")
|
||||
.map(|m| m.as_str().to_string())
|
||||
.ok_or(RSTError::NotFound("file_name"))?,
|
||||
height: cap.name("width").map(|m| m.as_str().to_string()),
|
||||
width: cap.name("width").map(|m| m.as_str().to_string()),
|
||||
alt: cap.name("alt").map(|m| m.as_str().to_string()),
|
||||
align: cap.name("align").map(|m| m.as_str().to_string()),
|
||||
};
|
||||
|
||||
Ok(image)
|
||||
}
|
||||
}
|
||||
|
||||
/// Renders RST links as HTML links
|
||||
///
|
||||
/// # Arguments
|
||||
///
|
||||
/// * `string` - input RST string
|
||||
pub fn parse_links(string: &str) -> Result<String, RSTError> {
|
||||
let re_link_ref = Regex::new(r"\n?.. _(.*): (.*)\n")?;
|
||||
let mut link_map: HashMap<String, String> = HashMap::new();
|
||||
|
||||
for cap in re_link_ref.captures_iter(string) {
|
||||
link_map.insert(String::from(&cap[1]), String::from(&cap[2]));
|
||||
}
|
||||
|
||||
let text: String = re_link_ref.replace_all(string, "").to_string();
|
||||
|
||||
let re_link = Regex::new(r"`(.*)`_")?;
|
||||
|
||||
let output = re_link.replace_all(&text, |cap: &Captures| {
|
||||
let link = match link_map.get(&cap[1]) {
|
||||
None => String::from(""),
|
||||
Some(link) => link.to_owned(),
|
||||
};
|
||||
|
||||
format!("<a class=\"link\" href=\"{}\">{}</a>", link, &cap[1])
|
||||
});
|
||||
|
||||
Ok(output.to_string())
|
||||
}
|
||||
|
||||
/// Renders RST images as HTML embedded images
|
||||
///
|
||||
/// # Arguments
|
||||
///
|
||||
/// * `string` - input rst string
|
||||
pub fn parse_images(string: &str) -> Result<String, RSTError> {
|
||||
let re_image = Regex::new(
|
||||
r".. image:: (?P<file_name>.*)\n( *((:height: (?P<height>.*))|(:width: (?P<width>.*))|(:scale: (?P<scale>.*%))|(:alt: (?P<alt>.*))|(:align: (?P<align>.*)))\n)*",
|
||||
)?;
|
||||
|
||||
Ok(re_image
|
||||
.replace_all(string, |cap: &Captures| RSTImage::try_from(cap).unwrap().to_html())
|
||||
.to_string())
|
||||
}
|
||||
@@ -0,0 +1,28 @@
|
||||
use regex::Error;
|
||||
|
||||
#[derive(Debug)]
|
||||
pub enum RSTError {
|
||||
/// Regex compile error
|
||||
RegexError(regex::Error),
|
||||
/// Required element not found
|
||||
NotFound(&'static str),
|
||||
}
|
||||
|
||||
impl std::error::Error for RSTError {}
|
||||
|
||||
impl From<regex::Error> for RSTError {
|
||||
/// From regex error
|
||||
fn from(e: Error) -> Self {
|
||||
Self::RegexError(e)
|
||||
}
|
||||
}
|
||||
|
||||
impl std::fmt::Display for RSTError {
|
||||
/// fmt error
|
||||
fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
|
||||
match self {
|
||||
RSTError::NotFound(s) => write!(f, "required element missing: `{}`", s),
|
||||
RSTError::RegexError(e) => write!(f, "regex compile error: `{:?}`", e),
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user