Added RST image parsing

+ Added DIP project
This commit is contained in:
Joey Hines 2020-10-04 10:41:46 -05:00
parent 9fbad90eb8
commit 68ecb118a9
7 changed files with 191 additions and 51 deletions

View File

@ -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,
}
};
@ -150,10 +151,9 @@ fn get_page(path: &Path) -> PageResult<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>");

View File

@ -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()
}

111
src/rst_parser/mod.rs Normal file
View File

@ -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())
}

View File

@ -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),
}
}
}

View File

@ -0,0 +1,33 @@
Motion Detector
===============
A project made for Auburn ELEC 7450: Digtal Image Processing. The source code can be found on my `Github`_
.. _GitHub: https://github.com/joeyahines/motion_detector
Goal
++++
The goal of this project was to detect motion on a video stream from a `VideoForLinux`_ source. The algorithm
can also be tested by loading in individual frames.
.. _VideoForLinux: https://en.wikipedia.org/wiki/Video4Linux
Implementation
++++++++++++++
The project was written in C and VideoForLinux for grabbing image data and `SDL`_ for rendering the video
output. A background model is built by implementing a moving average of the image. In addition to this,
a motion mask is implemented to desensitise the algorithm from background motion objects.
.. _SDL: https://www.libsdl.org/
Webcam output w/ motion highlighted:
.. image:: https://github.com/joeyahines/motion_detector/blob/master/docs/final_report/motion.png?&raw=true
:width: 60%
:height: auto
Motion detection layer:
.. image:: https://github.com/joeyahines/motion_detector/blob/master/docs/final_report/motion_image.png?raw=true
:width: 60%
:height: auto

View File

@ -42,5 +42,6 @@ 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. For example,
embedding images. I want to strike a balance between the aesthetic of a terminal and ease of use of a website.
As I continue to learn Rust, I plan to implement more features of RST into the raw file displays. ~~For example,
embedding images~~ (now onto text formatting...). I want to strike a balance between the aesthetic of a terminal and
ease of use of a website.

View File

@ -5,8 +5,8 @@ ls {{ page_data.site_file.link_name }}
{% endblock command %}
{% block content %}
{% for link in page_data.links %}
<br>
{% for link in page_data.links %}
<a class="link" href="{{ page_data.site_file.link_name}}/{{ link.link_name }}">{{ link.link_name }}</a>&nbsp;&nbsp;
{% endfor %}
<br>