From 99f17aa87203467d9504d46edf980b41cb183ca5 Mon Sep 17 00:00:00 2001 From: peterrabbit <peterrabbit@msi.home> Date: Mon, 22 Aug 2022 14:39:43 +0200 Subject: [PATCH] reorganized file structure --- example.json | 6 +- model.dia | Bin 3577 -> 3619 bytes src/app/args.rs | 26 +++++++++ src/{app_state.rs => app/config.rs} | 45 +-------------- src/app/mod.rs | 8 +++ src/app/preferences.rs | 2 + src/app/state.rs | 18 ++++++ src/main.rs | 4 +- src/{service.rs => service/mod.rs} | 0 src/static_files.rs | 2 +- src/tls_config.rs | 2 +- src/website/html.rs | 46 ++++++++++++++++ src/website/mod.rs | 5 ++ src/website/page.rs | 47 ++++++++++++++++ src/{ => website}/website.rs | 82 +--------------------------- templates/html_doc.html | 17 ------ templates/new_website.json | 32 +---------- 17 files changed, 164 insertions(+), 178 deletions(-) create mode 100644 src/app/args.rs rename src/{app_state.rs => app/config.rs} (65%) create mode 100644 src/app/mod.rs create mode 100644 src/app/preferences.rs create mode 100644 src/app/state.rs rename src/{service.rs => service/mod.rs} (100%) create mode 100644 src/website/html.rs create mode 100644 src/website/mod.rs create mode 100644 src/website/page.rs rename src/{ => website}/website.rs (53%) delete mode 100644 templates/html_doc.html diff --git a/example.json b/example.json index 28042f4..eb31b63 100644 --- a/example.json +++ b/example.json @@ -6,7 +6,8 @@ "description": "A website for Pijar", "image": "https://pijar.com/static/images/pijar_pic.png", "css": [], - "js": [] + "js": [], + "url_slug": "" }, "body": [ { @@ -30,7 +31,8 @@ } ] } - ] + ], + "sub_pages": [] }, "assets_index": { "images": [ diff --git a/model.dia b/model.dia index 597d424aac6e8a01527dacf244a11593bfc25138..6a0f8a70ac906e294656c8f730efb72eb6e387cd 100644 GIT binary patch literal 3619 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 R>aMvVE%O*0(|bZp^gpL49+Ln7 literal 3577 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 diff --git a/src/app/args.rs b/src/app/args.rs new file mode 100644 index 0000000..5deb639 --- /dev/null +++ b/src/app/args.rs @@ -0,0 +1,26 @@ +use std::path::PathBuf; +use structopt::StructOpt; + +#[derive(Clone, StructOpt)] +pub struct AppArgs { + #[structopt(short = "c", long = "ctx", default_value = "debug")] + pub context: String, + + #[structopt(short = "d", long = "dir")] + pub app_storage_root: Option<PathBuf>, + + #[structopt(long)] + pub load: Option<PathBuf>, + + #[structopt(short, long, default_value = "localhost")] + pub host: String, + + #[structopt(short, long, default_value = "8080")] + pub port: u16, + + #[structopt(long = "ptls", default_value = "8443")] + pub port_tls: u16, + + #[structopt(long = "certs_dir", default_value = "/etc/letsencrypt/live")] + pub ssl_certs_dir: PathBuf, +} diff --git a/src/app_state.rs b/src/app/config.rs similarity index 65% rename from src/app_state.rs rename to src/app/config.rs index 9cd3f67..42ce778 100644 --- a/src/app_state.rs +++ b/src/app/config.rs @@ -1,3 +1,4 @@ +use crate::app::AppArgs; use std::path::PathBuf; use structopt::StructOpt; @@ -7,30 +8,6 @@ pub enum AppContext { Production, } -#[derive(Clone, StructOpt)] -pub struct AppArgs { - #[structopt(short = "c", long = "ctx", default_value = "debug")] - pub context: String, - - #[structopt(short = "d", long = "dir")] - pub app_storage_root: Option<PathBuf>, - - #[structopt(long)] - pub load: Option<PathBuf>, - - #[structopt(short, long, default_value = "localhost")] - pub host: String, - - #[structopt(short, long, default_value = "8080")] - pub port: u16, - - #[structopt(long = "ptls", default_value = "8443")] - pub port_tls: u16, - - #[structopt(long = "certs_dir", default_value = "/etc/letsencrypt/live")] - pub ssl_certs_dir: PathBuf, -} - #[derive(Clone)] pub struct AppConfig { pub exec_path: PathBuf, @@ -91,23 +68,3 @@ impl AppConfig { } } } - -#[derive(Clone)] -pub struct AppState { - pub config: AppConfig, - pub preferences: AppPreference, - // authentication - // ... -} - -#[derive(Clone)] -pub struct AppPreference {} - -impl AppState { - pub fn new() -> Self { - AppState { - config: AppConfig::new(), - preferences: AppPreference {}, - } - } -} diff --git a/src/app/mod.rs b/src/app/mod.rs new file mode 100644 index 0000000..e5bee9e --- /dev/null +++ b/src/app/mod.rs @@ -0,0 +1,8 @@ +mod args; +mod config; +mod preferences; +mod state; +pub use args::*; +pub use config::*; +pub use preferences::*; +pub use state::*; diff --git a/src/app/preferences.rs b/src/app/preferences.rs new file mode 100644 index 0000000..f097a65 --- /dev/null +++ b/src/app/preferences.rs @@ -0,0 +1,2 @@ +#[derive(Clone)] +pub struct AppPreferences {} diff --git a/src/app/state.rs b/src/app/state.rs new file mode 100644 index 0000000..8d0dc75 --- /dev/null +++ b/src/app/state.rs @@ -0,0 +1,18 @@ +use crate::app::{AppConfig, AppPreferences}; + +#[derive(Clone)] +pub struct AppState { + pub config: AppConfig, + pub preferences: AppPreferences, + // authentication + // ... +} + +impl AppState { + pub fn new() -> Self { + AppState { + config: AppConfig::new(), + preferences: AppPreferences {}, + } + } +} diff --git a/src/main.rs b/src/main.rs index 1bd1725..c996be1 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,4 +1,4 @@ -mod app_state; +mod app; mod service; mod static_files; mod testing; @@ -6,7 +6,7 @@ mod tls_config; mod website; use actix_web::{App, HttpServer}; use actix_web_lab::middleware::RedirectHttps; -use app_state::AppState; +use app::AppState; use static_files::StaticFilesManager; use tls_config::tls_config; use website::WebSite; diff --git a/src/service.rs b/src/service/mod.rs similarity index 100% rename from src/service.rs rename to src/service/mod.rs diff --git a/src/static_files.rs b/src/static_files.rs index c4fbab6..4da405f 100644 --- a/src/static_files.rs +++ b/src/static_files.rs @@ -1,4 +1,4 @@ -use crate::app_state::AppState; +use crate::app::AppState; use std::path::{Path, PathBuf}; pub struct StaticFilesManager { diff --git a/src/tls_config.rs b/src/tls_config.rs index 61c23e8..b69f528 100644 --- a/src/tls_config.rs +++ b/src/tls_config.rs @@ -1,4 +1,4 @@ -use crate::app_state::AppConfig; +use crate::app::AppConfig; pub fn tls_config(app_config: &AppConfig) -> rustls::ServerConfig { let certs_dir = app_config.ssl_certs_dir.clone(); diff --git a/src/website/html.rs b/src/website/html.rs new file mode 100644 index 0000000..9385527 --- /dev/null +++ b/src/website/html.rs @@ -0,0 +1,46 @@ +use crate::website::page::PageData; +use regex::{Captures, Regex}; +use serde::{Deserialize, Serialize}; + +pub const HTML_DOC_TEMPLATE: &'static str = " +<html lang='{lang}'> +<head> + <meta charset='UTF-8'> + <meta http-equiv='X-UA-Compatible' content='IE=edge'> + <meta name='viewport' content='width=device-width, initial-scale=1.0'> + <meta name='description' content='{description}'> + <title>{title}</title> + <link rel='stylesheet' href='{css}'> +</head> + +<body> + {body} +</body> + +<script src='{js}'></script> + +</html> +"; + +#[derive(Debug, Serialize, Deserialize, Clone)] +pub struct HtmlDoc(String); + +impl HtmlDoc { + pub fn from_page_data(page_data: &PageData) -> Self { + let re = Regex::new(r#"\{[a-z]+\}"#).unwrap(); + + let html = re + .replace_all(HTML_DOC_TEMPLATE, |captures: &Captures| { + let placeholder = captures.iter().next().unwrap().unwrap().as_str(); + let placeholder = placeholder[1..placeholder.len() - 1].to_owned(); + page_data.field_from_str_key(placeholder) + }) + .to_string(); + + HtmlDoc(html) + } + + pub fn to_string(&self) -> String { + self.0.clone() + } +} diff --git a/src/website/mod.rs b/src/website/mod.rs new file mode 100644 index 0000000..fcd415f --- /dev/null +++ b/src/website/mod.rs @@ -0,0 +1,5 @@ +mod html; +mod page; +mod website; + +pub use website::*; diff --git a/src/website/page.rs b/src/website/page.rs new file mode 100644 index 0000000..4f38e7a --- /dev/null +++ b/src/website/page.rs @@ -0,0 +1,47 @@ +use crate::website::html::HtmlDoc; +use serde::{Deserialize, Serialize}; + +#[derive(Debug, Serialize, Deserialize, Clone)] +pub struct PageData { + pub title: String, + pub lang: String, + pub description: String, + pub slug: String, + pub html_body: String, + pub css_src: Option<String>, + pub js_src: Option<String>, +} + +#[derive(Debug, Serialize, Deserialize, Clone)] +pub struct WebPage { + pub page_data: PageData, + pub html_doc: HtmlDoc, +} + +impl PageData { + pub fn to_web_page(&self) -> WebPage { + WebPage { + page_data: self.clone(), + html_doc: HtmlDoc::from_page_data(&self), + } + } + + pub fn field_from_str_key(&self, key: String) -> String { + match &key[..] { + "title" => self.title.to_owned(), + "lang" => self.lang.to_owned(), + "description" => self.description.to_owned(), + "slug" => self.slug.to_owned(), + "body" => self.html_body.to_owned(), + "css" => self.css_src.as_ref().unwrap_or(&String::new()).to_owned(), + "js" => self.js_src.as_ref().unwrap_or(&String::new()).to_owned(), + _ => String::new(), + } + } +} + +#[derive(Debug, Serialize, Deserialize, Clone)] +pub struct PagesTree { + pub page_data: PageData, + pub sub_pages: Option<Vec<PagesTree>>, +} diff --git a/src/website.rs b/src/website/website.rs similarity index 53% rename from src/website.rs rename to src/website/website.rs index c65d5c5..6a6cb1f 100644 --- a/src/website.rs +++ b/src/website/website.rs @@ -1,87 +1,9 @@ -use crate::app_state::AppConfig; -use regex::{Captures, Regex}; +use crate::app::AppConfig; +use crate::website::page::{PagesTree, WebPage}; use serde::{Deserialize, Serialize}; use std::collections::HashMap; use std::path::PathBuf; -#[derive(Debug, Serialize, Deserialize, Clone)] -pub struct PageData { - pub title: String, - pub lang: String, - pub description: String, - pub slug: String, - pub html_body: String, - pub css_src: Option<String>, - pub js_src: Option<String>, -} - -#[derive(Debug, Serialize, Deserialize, Clone)] -pub struct HtmlDoc(String); - -impl HtmlDoc { - fn load_template() -> String { - std::fs::read_to_string( - std::env::current_dir() - .unwrap() - .join("templates") - .join("html_doc.html"), - ) - .expect("Missing html_doc template") - } - - pub fn from_page_data(page_data: &PageData) -> Self { - let re = Regex::new(r#"\{[a-z]+\}"#).unwrap(); - - let html = re - .replace_all(&HtmlDoc::load_template(), |captures: &Captures| { - let placeholder = captures.iter().next().unwrap().unwrap().as_str(); - let placeholder = placeholder[1..placeholder.len() - 1].to_owned(); - page_data.field_from_str_key(placeholder) - }) - .to_string(); - - HtmlDoc(html) - } - - pub fn to_string(&self) -> String { - self.0.clone() - } -} - -#[derive(Debug, Serialize, Deserialize, Clone)] -pub struct WebPage { - pub page_data: PageData, - pub html_doc: HtmlDoc, -} - -impl PageData { - pub fn to_web_page(&self) -> WebPage { - WebPage { - page_data: self.clone(), - html_doc: HtmlDoc::from_page_data(&self), - } - } - - pub fn field_from_str_key(&self, key: String) -> String { - match &key[..] { - "title" => self.title.to_owned(), - "lang" => self.lang.to_owned(), - "description" => self.description.to_owned(), - "slug" => self.slug.to_owned(), - "body" => self.html_body.to_owned(), - "css" => self.css_src.as_ref().unwrap_or(&String::new()).to_owned(), - "js" => self.js_src.as_ref().unwrap_or(&String::new()).to_owned(), - _ => String::new(), - } - } -} - -#[derive(Debug, Serialize, Deserialize, Clone)] -pub struct PagesTree { - pub page_data: PageData, - pub sub_pages: Option<Vec<PagesTree>>, -} - #[derive(Debug, Serialize, Deserialize, Clone)] pub struct WebSite { pages_tree: PagesTree, diff --git a/templates/html_doc.html b/templates/html_doc.html deleted file mode 100644 index e856898..0000000 --- a/templates/html_doc.html +++ /dev/null @@ -1,17 +0,0 @@ -<html lang="{lang}"> - -<head> - <meta charset="UTF-8"> - <meta http-equiv="X-UA-Compatible" content="IE=edge"> - <meta name="viewport" content="width=device-width, initial-scale=1.0"> - <meta name="description" content="{description}"> - <title>{title}</title> - <link rel="stylesheet" href="{css}"> -</head> - -<body> - {body} -</body> -<script src="{js}"></script> - -</html> \ No newline at end of file diff --git a/templates/new_website.json b/templates/new_website.json index 92a78fa..c6c845b 100644 --- a/templates/new_website.json +++ b/templates/new_website.json @@ -6,35 +6,5 @@ "description": "A new website", "html_body": "<h1>New Website</h1>" }, - "sub_pages": [ - { - "page_data": { - "title": "A sub page", - "lang": "en", - "slug": "subpage", - "description": "A sub page of the new web site", - "html_body": "<h1>A sub page</h1>" - } - }, - { - "page_data": { - "title": "Some other page", - "lang": "en", - "slug": "otherpage", - "description": "Some other page of the new web site", - "html_body": "<h1>Another page</h1>" - }, - "sub_pages": [ - { - "page_data": { - "title": "A sub page of the other page", - "lang": "en", - "slug": "othersubpage", - "description": "A sub page of the other page of the new web site", - "html_body": "<h1>A subpage</h1>" - } - } - ] - } - ] + "sub_pages": [] } \ No newline at end of file -- GitLab