|
@@ -1,5 +1,6 @@
|
|
|
mod articles_repository;
|
|
|
mod config;
|
|
|
+mod theme;
|
|
|
mod vcs;
|
|
|
|
|
|
extern crate chrono;
|
|
@@ -13,19 +14,17 @@ use std::{env, fs, io};
|
|
|
use articles_repository::{ArticlesRepository, FsRepository};
|
|
|
use config::Configuration;
|
|
|
use pulldown_cmark::{html, Options, Parser};
|
|
|
+use theme::Theme;
|
|
|
|
|
|
#[get("")]
|
|
|
async fn show_articles_list() -> impl Responder {
|
|
|
let repo: FsRepository = FsRepository {};
|
|
|
|
|
|
const CONTENT_FOLDER: &str = "./content";
|
|
|
- let estimated_path: String = env::current_dir()
|
|
|
- .unwrap_or_default()
|
|
|
- .to_str()
|
|
|
- .unwrap_or_default()
|
|
|
- .to_string();
|
|
|
-
|
|
|
- log::trace!("Estimated content repository: {estimated_path}/{CONTENT_FOLDER}");
|
|
|
+ let exe_dir = env::current_dir()
|
|
|
+ .and_then(|dir| io::Result::Ok(dir.to_str().unwrap_or("").to_string()))
|
|
|
+ .unwrap();
|
|
|
+ log::trace!("Estimated content repository: {exe_dir}/{CONTENT_FOLDER}");
|
|
|
|
|
|
let paths = repo.get_directory_listing(&CONTENT_FOLDER).join("\n");
|
|
|
|
|
@@ -35,21 +34,22 @@ async fn show_articles_list() -> impl Responder {
|
|
|
#[get("/{path:.+}")]
|
|
|
async fn show_article(path: web::Path<(String,)>) -> impl Responder {
|
|
|
let p = &path.0;
|
|
|
- let file = fs::read_to_string(p.as_str());
|
|
|
-
|
|
|
- match file {
|
|
|
- Ok(content) => {
|
|
|
- log::trace!("Opening article located {}", p.as_str());
|
|
|
- let mut options = Options::empty();
|
|
|
- options.insert(Options::ENABLE_STRIKETHROUGH);
|
|
|
- let parser = Parser::new_ext(content.as_str(), options);
|
|
|
- let mut html_output = String::new();
|
|
|
- html::push_html(&mut html_output, parser);
|
|
|
-
|
|
|
- HttpResponse::Ok().body(html_output)
|
|
|
- }
|
|
|
- Err(error) => {
|
|
|
- log::error!("Article located at path {} was not found.", p.as_str());
|
|
|
+
|
|
|
+ let exe_dir = env::current_dir()
|
|
|
+ .and_then(|dir| io::Result::Ok(dir.to_str().unwrap_or("").to_string()))
|
|
|
+ .unwrap();
|
|
|
+
|
|
|
+ let theme_path = format!("{}/www/themes/default", exe_dir);
|
|
|
+ log::info!("Theme path: {}", theme_path);
|
|
|
+
|
|
|
+ let theme = Theme::new(theme_path);
|
|
|
+
|
|
|
+ let rendered = theme.render_as_page(&p);
|
|
|
+
|
|
|
+ match rendered {
|
|
|
+ Ok(content) => HttpResponse::Ok().body(content),
|
|
|
+ Err(e) => {
|
|
|
+ log::error!("Couldn't find article located at '{}'. Error: {}", p, e);
|
|
|
HttpResponse::NotFound().finish()
|
|
|
}
|
|
|
}
|
|
@@ -73,16 +73,23 @@ async fn main() -> std::io::Result<()> {
|
|
|
message
|
|
|
))
|
|
|
})
|
|
|
- .level(log::LevelFilter::Info)
|
|
|
+ .level(log::LevelFilter::Trace)
|
|
|
.chain(std::io::stdout())
|
|
|
.apply();
|
|
|
|
|
|
HttpServer::new(|| {
|
|
|
- App::new().wrap(Logger::default()).service(
|
|
|
- web::scope("/a")
|
|
|
- .service(show_article)
|
|
|
- .service(show_articles_list),
|
|
|
- )
|
|
|
+ App::new()
|
|
|
+ .wrap(Logger::default())
|
|
|
+ .service(actix_files::Files::new("/css", "./www/themes/default/css"))
|
|
|
+ .service(actix_files::Files::new(
|
|
|
+ "/images",
|
|
|
+ "./www/themes/default/images",
|
|
|
+ ))
|
|
|
+ .service(
|
|
|
+ web::scope("/a")
|
|
|
+ .service(show_article)
|
|
|
+ .service(show_articles_list),
|
|
|
+ )
|
|
|
})
|
|
|
.bind((config.listen_addr, config.listen_port))?
|
|
|
.run()
|