use std::io;
use std::io::ErrorKind;
use regex::Regex;
use crate::content::content_file::ContentFile;
use crate::content::content_format::ContentFormat;
use crate::content::content_renderer::{ContentRenderer, ImagePrefix, RenderOptions};
use crate::content::parsing_utils::{extract_content, parse_texted_header, parse_title_html};
use crate::content::Content;
pub struct HtmlRenderer {}
impl ContentRenderer for HtmlRenderer {
fn render(content_file: &ContentFile, render_options: RenderOptions) -> io::Result<Content> {
if content_file.format != ContentFormat::Html {
return Err(io::Error::new(ErrorKind::InvalidData, format!("Unsupported format: {:?}", content_file.format)));
}
let link = content_file.link.clone();
let (header, lines, maybe_line) = parse_texted_header(&content_file.file_path, content_file.raw_content.lines())?;
let (title, lines, _title_line) = parse_title_html(lines, maybe_line);
let content = extract_content(lines, &render_options);
let rendered = match render_options {
RenderOptions::PreviewOnly(_preview_opt, ImagePrefix(prefix)) => Self::change_images(&prefix, &content),
RenderOptions::FullContent => content,
};
Ok(Content {
header,
link,
title,
rendered,
})
}
}
impl HtmlRenderer {
fn change_images(prefix: &str, html: &str) -> String {
let prefix = if prefix.ends_with("/") {
prefix.to_string()
} else {
format!("{}/", prefix)
};
let img_regex = Regex::new(r#"<img[^>]*src="([^"]*)"[^>]*>"#).unwrap();
let result = img_regex.replace_all(html, |captures: ®ex::Captures| {
let src = captures.get(1).unwrap().as_str();
let prefixed_src = if src.contains("://") {
src.to_string()
} else {
format!(r#"{}{}"#, prefix, src)
};
captures.get(0).unwrap().as_str().replace(src, &prefixed_src)
});
result.to_string()
}
}
#[cfg(test)]
mod tests {
use std::path::PathBuf;
use crate::test_data::POST_DATA_HTML;
use super::*;
#[test]
fn test_full_content_html() {
let file_name = PathBuf::from("posts/20200522_how_to_write_a_code_reviewindex.md");
let content = ContentFile {
link: "".to_string(),
file_path: file_name,
format: ContentFormat::Html,
raw_content: POST_DATA_HTML.to_string(),
};
let content = HtmlRenderer::render(&content, RenderOptions::FullContent).unwrap();
assert_eq!(content.rendered, r##"<p>How to be a great software engineer?</p>
<p>Someone asked me this question today and I didn’t have an answer. After thinking for a while, I came up with a list of what I try to do myself.</p>
<p>Disclaimer: I don't think I am a great engineer, but I would love to have listened to that myself when I started my career, over 20 years ago.</p>
<p>I will divide this in parts, non-technical and technical</p>
<!-- more -->
<h2>Non technical</h2>
<h3>Have a honest image of yourself</h3>
<p>You finished university and learned a lot. You solved many hard problems. It's common to think you are awesome and the smartest person in the planet. Some day in your life, you will find that you are not and that there are many developers much better than you. Not in capacity, but in wisdom and knowledge. <strong>The earlier you find that, the better.</strong> This will drive you to improve yourself as you now recognize better your weakest points.</p>
<h3>The awesome thing you learned doesn't solve all the problems</h3>
<p>The less knowledge you have, the more you will feel that something awesome you learned is the solution for everything. <strong>There is no Saint Graal</strong>. Always search for alternatives, even if they don't look good. The more you know, the more you will see the problems of new trends and concepts and you will be able to choose the best solution for the problem you need to solve</p>
"##)
}
#[test]
fn test_change_images() {
let html = r#"<html>
<body>
<img src="image1.jpg">
<img some="212" src="image2.jpg">
<img style="asd" src="image3.jpg" type="ddd">
<img style="asd" src="http://not-change/image4.jpg" type="ddd">
<img style="asd" src="https://not-change/image5.jpg" type="ddd">
<img src="ftp://not-change/image5.jpg">
</body>
</html>"#;
let prefixed_html = HtmlRenderer::change_images("view/post_name", html);
assert_eq!(prefixed_html, r#"<html>
<body>
<img src="view/post_name/image1.jpg">
<img some="212" src="view/post_name/image2.jpg">
<img style="asd" src="view/post_name/image3.jpg" type="ddd">
<img style="asd" src="http://not-change/image4.jpg" type="ddd">
<img style="asd" src="https://not-change/image5.jpg" type="ddd">
<img src="ftp://not-change/image5.jpg">
</body>
</html>"#);
}
#[test]
fn test_change_images_no_image() {
let html = r#"<html>
<body>
<span>some text</span>
</body>
</html>"#;
let prefixed_html = HtmlRenderer::change_images("view/post_name/", html);
assert_eq!(prefixed_html, r#"<html>
<body>
<span>some text</span>
</body>
</html>"#);
}
}