From 6e6e062c51506e82653d13f499b0adf35755deda Mon Sep 17 00:00:00 2001 From: _ <> Date: Sun, 29 Nov 2020 22:56:25 +0000 Subject: [PATCH] :recycle: Move Markdown previewing to its own file --- crates/ptth_server/src/file_server/errors.rs | 13 +-- .../ptth_server/src/file_server/markdown.rs | 56 +++++++++++++ crates/ptth_server/src/file_server/mod.rs | 81 +++++++------------ crates/ptth_server/src/file_server/tests.rs | 17 ---- 4 files changed, 88 insertions(+), 79 deletions(-) create mode 100644 crates/ptth_server/src/file_server/markdown.rs diff --git a/crates/ptth_server/src/file_server/errors.rs b/crates/ptth_server/src/file_server/errors.rs index 9845340..dbb9127 100644 --- a/crates/ptth_server/src/file_server/errors.rs +++ b/crates/ptth_server/src/file_server/errors.rs @@ -1,14 +1,5 @@ use thiserror::Error; -#[derive (Debug, Error, PartialEq)] -pub enum MarkdownError { - #[error ("File is too big to process")] - TooBig, - - #[error ("File is not UTF-8")] - NotUtf8, -} - #[derive (Debug, Error)] pub enum FileServerError { #[error ("Handlebars render error")] @@ -29,8 +20,8 @@ pub enum FileServerError { #[error ("File path is not UTF-8")] FilePathNotUtf8, - #[error ("Markdown error")] - Markdown (#[from] MarkdownError), + //#[error ("Markdown error")] + //Markdown (#[from] super::markdown::Error), #[error ("Invalid URI")] InvalidUri (#[from] http::uri::InvalidUri), diff --git a/crates/ptth_server/src/file_server/markdown.rs b/crates/ptth_server/src/file_server/markdown.rs new file mode 100644 index 0000000..2930481 --- /dev/null +++ b/crates/ptth_server/src/file_server/markdown.rs @@ -0,0 +1,56 @@ +#[derive (Debug, thiserror::Error, PartialEq)] +pub enum Error { + #[error ("File is too big to preview as Markdown")] + TooBig, + + #[error ("File is not UTF-8")] + NotUtf8, +} + +fn render (bytes: &[u8], out: &mut String) -> Result <(), Error> { + use pulldown_cmark::{Parser, Options, html}; + + let markdown_input = match std::str::from_utf8 (bytes) { + Err (_) => return Err (Error::NotUtf8), + Ok (x) => x, + }; + + let mut options = Options::empty (); + options.insert (Options::ENABLE_STRIKETHROUGH); + let parser = Parser::new_ext (markdown_input, options); + + html::push_html (out, parser); + + Ok (()) +} + +pub fn render_styled (bytes: &[u8]) -> Result { + // Write to String buffer. + let mut out = String::new (); + + out.push_str (""); + render (bytes, &mut out)?; + out.push_str (""); + + Ok (out) +} + +#[cfg (test)] +mod tests { + #[test] + fn markdown () { + use super::*; + + for (input, expected) in vec! [ + ("", ""), + ( + "Hello world, this is a ~~complicated~~ *very simple* example.", + "

Hello world, this is a complicated very simple example.

\n" + ), + ].into_iter () { + let mut out = String::default (); + render (input.as_bytes (), &mut out).expect ("Markdown sample failed"); + assert_eq! (expected, &out); + } + } +} diff --git a/crates/ptth_server/src/file_server/mod.rs b/crates/ptth_server/src/file_server/mod.rs index fe2c497..a34193f 100644 --- a/crates/ptth_server/src/file_server/mod.rs +++ b/crates/ptth_server/src/file_server/mod.rs @@ -49,12 +49,11 @@ use ptth_core::{ }; pub mod errors; +mod markdown; mod range; -use errors::{ - FileServerError, - MarkdownError, -}; +use errors::FileServerError; +use markdown::render_styled; mod emoji { pub const VIDEO: &str = "\u{1f39e}\u{fe0f}"; @@ -316,46 +315,6 @@ async fn serve_file ( Ok (response) } -fn serve_error ( - status_code: StatusCode, - msg: &str -) --> Response -{ - let mut resp = Response::default (); - resp.status_code (status_code); - resp.body_bytes (msg.as_bytes ().to_vec ()); - resp -} - -fn render_markdown (bytes: &[u8], out: &mut String) -> Result <(), MarkdownError> { - use pulldown_cmark::{Parser, Options, html}; - - let markdown_input = match std::str::from_utf8 (bytes) { - Err (_) => return Err (MarkdownError::NotUtf8), - Ok (x) => x, - }; - - let mut options = Options::empty (); - options.insert (Options::ENABLE_STRIKETHROUGH); - let parser = Parser::new_ext (markdown_input, options); - - html::push_html (out, parser); - - Ok (()) -} - -fn render_markdown_styled (bytes: &[u8]) -> Result { - // Write to String buffer. - let mut out = String::new (); - - out.push_str (""); - render_markdown (bytes, &mut out)?; - out.push_str (""); - - Ok (out) -} - // Sort of an internal API endpoint to make testing work better. // Eventually we could expose this as JSON or Msgpack or whatever. For now // it's just a Rust struct that we can test on without caring about @@ -387,7 +346,7 @@ enum InternalResponse { ServeDir (ServeDirParams), ServeFile (ServeFileParams), - MarkdownErr (MarkdownError), + MarkdownErr (markdown::Error), MarkdownPreview (String), } @@ -451,14 +410,17 @@ async fn internal_serve_file ( } if file_len > MAX_BUF_SIZE.into () { - InternalResponse::MarkdownErr (MarkdownError::TooBig) + InternalResponse::MarkdownErr (markdown::Error::TooBig) } else { let mut buffer = vec! [0_u8; MAX_BUF_SIZE.try_into ().expect ("Couldn't fit u32 into usize")]; let bytes_read = file.read (&mut buffer).await?; buffer.truncate (bytes_read); - InternalResponse::MarkdownPreview (render_markdown_styled (&buffer)?) + match render_styled (&buffer) { + Ok (x) => InternalResponse::MarkdownPreview (x), + Err (x) => InternalResponse::MarkdownErr (x), + } } } else { @@ -565,6 +527,18 @@ pub async fn serve_all ( { use InternalResponse::*; + fn serve_error >> ( + status_code: StatusCode, + msg: S + ) + -> Response + { + let mut resp = Response::default (); + resp.status_code (status_code); + resp.body_bytes (msg.into ()); + resp + } + Ok (match internal_serve_all (root, method, uri, headers, hidden_path).await? { Favicon => serve_error (StatusCode::NotFound, ""), Forbidden => serve_error (StatusCode::Forbidden, "403 Forbidden"), @@ -594,10 +568,15 @@ pub async fn serve_all ( send_body, range, }) => serve_file (file.into_inner (), send_body, range).await?, - MarkdownErr (e) => match e { - MarkdownError::TooBig => serve_error (StatusCode::InternalServerError, "File is too big to preview as Markdown"), - //MarkdownError::NotMarkdown => serve_error (StatusCode::BadRequest, "File is not Markdown"), - MarkdownError::NotUtf8 => serve_error (StatusCode::BadRequest, "File is not UTF-8"), + MarkdownErr (e) => { + use markdown::Error::*; + let code = match &e { + TooBig => StatusCode::InternalServerError, + //NotMarkdown => serve_error (StatusCode::BadRequest, "File is not Markdown"), + NotUtf8 => StatusCode::BadRequest, + }; + + serve_error (code, e.to_string ()) }, MarkdownPreview (s) => serve_html (s), }) diff --git a/crates/ptth_server/src/file_server/tests.rs b/crates/ptth_server/src/file_server/tests.rs index 0ada930..a78e6f1 100644 --- a/crates/ptth_server/src/file_server/tests.rs +++ b/crates/ptth_server/src/file_server/tests.rs @@ -181,20 +181,3 @@ fn file_server () { fn parse_uri () { assert! (http::Uri::from_maybe_shared ("/").is_ok ()); } - -#[test] -fn markdown () { - use super::*; - - for (input, expected) in vec! [ - ("", ""), - ( - "Hello world, this is a ~~complicated~~ *very simple* example.", - "

Hello world, this is a complicated very simple example.

\n" - ), - ].into_iter () { - let mut out = String::default (); - render_markdown (input.as_bytes (), &mut out).expect ("Markdown sample failed"); - assert_eq! (expected, &out); - } -}