Pour tout problème contactez-nous par mail : support@froggit.fr | La FAQ :grey_question: | Rejoignez-nous sur le Chat :speech_balloon:

Skip to content
Snippets Groups Projects
Commit 9dd20cac authored by peterrabbit's avatar peterrabbit
Browse files

html doc formatting

parent d21d08a7
No related branches found
No related tags found
No related merge requests found
......@@ -375,6 +375,7 @@ name = "cms_rust"
version = "0.1.0"
dependencies = [
"actix-web",
"regex",
"rustls",
"rustls-pemfile",
"serde",
......
......@@ -11,3 +11,4 @@ rustls = "0.20.6"
rustls-pemfile = "1.0.1"
serde = { version = "1.0.143", features = ["derive"] }
serde_json = "1.0.83"
regex = "1.6"
mod website;
use actix_web::{get, App, HttpResponse, HttpServer, Responder};
use std::path::PathBuf;
use website::WebSite;
fn load_website_template() -> WebSite {
......@@ -8,18 +9,18 @@ fn load_website_template() -> WebSite {
.join("templates")
.join("new_website.json");
let site_template = std::fs::read_to_string(site_template_path).unwrap();
WebSite::new(serde_json::from_str(&site_template).unwrap())
WebSite::from_json_str(&site_template)
}
#[get("/{pth:.*}")]
async fn page(
website: actix_web::web::Data<WebSite>,
pth: actix_web::web::Path<String>,
pth: actix_web::web::Path<PathBuf>,
) -> impl Responder {
let pth = format!("/{}/", pth.into_inner()); // BUG Use trailing slash middleware ? or match root or not root
let pth = pth.into_inner();
match website.get_page_by_url(&pth) {
Some(page) => HttpResponse::Ok().body(page.html_doc.clone()),
None => HttpResponse::NotFound().body(format!("Not found {}", pth)),
Some(page) => HttpResponse::Ok().body(page.html_doc.to_string()),
None => HttpResponse::NotFound().body(format!("Not found {}", pth.display())),
}
}
......
use regex::{Captures, Regex};
use serde::{Deserialize, Serialize};
use std::collections::HashMap;
use std::path::PathBuf;
#[derive(Debug, Serialize, Deserialize, Clone)]
pub struct PageData {
......@@ -8,19 +10,65 @@ pub struct PageData {
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 {
pub fn from_page_data(page_data: &PageData) -> Self {
let html_doc = std::fs::read_to_string(
std::env::current_dir()
.unwrap()
.join("templates")
.join("html_doc.html"),
)
.expect("Missing html_doc template");
let re = Regex::new(r#"\{[a-z]+\}"#).unwrap();
let html_doc = re
.replace_all(&html_doc, |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_doc)
}
pub fn to_string(&self) -> String {
self.0.clone()
}
}
#[derive(Debug, Serialize, Deserialize, Clone)]
pub struct WebPage {
pub page_data: PageData,
pub html_doc: String,
pub html_doc: HtmlDoc,
}
impl PageData {
pub fn to_web_page(&self) -> WebPage {
WebPage {
page_data: self.clone(),
html_doc: self.html_body.clone(), // TMP
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(),
}
}
}
......@@ -34,13 +82,13 @@ pub struct PagesTree {
#[derive(Debug, Serialize, Deserialize, Clone)]
pub struct WebSite {
pages_tree: PagesTree,
pages_index_by_url: HashMap<String, WebPage>,
pages_index_by_url: HashMap<PathBuf, WebPage>,
}
impl WebSite {
pub fn new(pages_tree: PagesTree) -> Self {
let mut pages_index_by_url = HashMap::new();
WebSite::create_index_by_url(&mut pages_index_by_url, &pages_tree, String::new());
WebSite::create_index_by_url(&mut pages_index_by_url, &pages_tree, PathBuf::from("/"));
WebSite {
pages_tree,
......@@ -48,25 +96,29 @@ impl WebSite {
}
}
pub fn from_json_str(json: &str) -> Self {
WebSite::new(serde_json::from_str(json).unwrap())
}
fn create_index_by_url(
index: &mut HashMap<String, WebPage>,
index: &mut HashMap<PathBuf, WebPage>,
pages_tree: &PagesTree,
from_url: String,
from_url: PathBuf,
) {
let page_data = pages_tree.page_data.clone();
let url = format!("{}{}/", from_url, page_data.slug);
let url = from_url.join(&page_data.slug);
index.insert(url.to_owned(), page_data.to_web_page());
index.insert(url.clone(), page_data.to_web_page());
if let Some(sub_pages) = &pages_tree.sub_pages {
for pt in sub_pages {
WebSite::create_index_by_url(index, pt, url.to_owned());
WebSite::create_index_by_url(index, pt, url.clone());
}
}
}
pub fn get_page_by_url(&self, url: &String) -> Option<&WebPage> {
self.pages_index_by_url.get(url)
pub fn get_page_by_url(&self, url: &PathBuf) -> Option<&WebPage> {
self.pages_index_by_url.get(&PathBuf::from("/").join(url))
}
}
......@@ -109,14 +161,13 @@ mod test_website {
#[test]
fn test_index_pages_by_slug() {
let pages_tree: PagesTree = serde_json::from_str(JSON_TEMPLATE).unwrap();
let website = WebSite::new(pages_tree);
let root_page = website.get_page_by_url(&"/".to_string());
let website = WebSite::from_json_str(JSON_TEMPLATE);
let root_page = website.get_page_by_url(&PathBuf::from("/"));
assert!(root_page.is_some());
let root_page = root_page.unwrap();
assert_eq!(root_page.page_data.html_body, "<h1>Test Website</h1>");
let sub_page = website.get_page_by_url(&"/subpage/".to_string());
let sub_page = website.get_page_by_url(&PathBuf::from("/subpage"));
assert!(sub_page.is_some());
let sub_page = sub_page.unwrap();
assert_eq!(sub_page.page_data.html_body, "<h1>A sub page</h1>");
......
<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
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment