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 697bf621 authored by peterrabbit's avatar peterrabbit
Browse files

wip build html rendering

parent c0676f8f
No related branches found
No related tags found
No related merge requests found
......@@ -1316,18 +1316,18 @@ checksum = "93f6841e709003d68bb2deee8c343572bf446003ec20a583e76f7b15cebf3711"
[[package]]
name = "serde"
version = "1.0.143"
version = "1.0.144"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "53e8e5d5b70924f74ff5c6d64d9a5acd91422117c60f48c4e07855238a254553"
checksum = "0f747710de3dcd43b88c9168773254e809d8ddbdf9653b84e2554ab219f17860"
dependencies = [
"serde_derive",
]
[[package]]
name = "serde_derive"
version = "1.0.143"
version = "1.0.144"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d3d8e8de557aee63c26b85b947f5e59b690d0454c753f3adeb5cd7835ab88391"
checksum = "94ed3a816fb1d101812f83e789f888322c34e291f894f19590dc310963e87a00"
dependencies = [
"proc-macro2",
"quote",
......
......@@ -9,7 +9,7 @@ edition = "2021"
actix-web = { version = "4.1.0", features = ["rustls", "secure-cookies"] }
rustls = "0.20.6"
rustls-pemfile = "1.0.1"
serde = { version = "1.0.143", features = ["derive"] }
serde = { version = "1.0.144", features = ["derive"] }
serde_json = "1.0.83"
regex = "1.6"
fs_extra = "1.2"
......
{
"root_page": {
"template": "Pijar Custom Template",
"template_name": "Pijar Custom Template",
"metadata": {
"title": "Hello Pijar !",
"description": "A website for Pijar",
......@@ -57,7 +57,7 @@
"layout": {
"display": "grid"
},
"fixed_contents": [
"contents": [
{
"tag": "nav",
"contents": [
......
#[cfg(test)]
pub const TEST_JSON_WEBSITE: &'static str = "
{
\"page_data\": {
\"title\": \"Test Website\",
\"slug\": \"\",
\"lang\": \"en\",
\"description\": \"A test website\",
\"html_body\": \"<h1>Test Website</h1>\"
\"root_page\": {
\"template_name\": \"TEST TEMPLATE\",
\"metadata\": {
\"title\": \"TEST\",
\"description\": \"TEST DESCRIPTION\",
\"image\": \"https://test/static/images/test.png\",
\"css\": [],
\"lang\":\"en\",
\"js\": [],
\"url_slug\": \"\"
},
\"body\": [
{
\"layout\": {
\"display\": \"flex\",
\"padding\": \"20px\"
},
\"contents\": [
{
\"tag\": \"h1\",
\"text\": \"testing\"
}
]
}
],
\"sub_pages\": [
{
\"template_name\": \"TEST TEMPLATE\",
\"metadata\": {
\"title\": \"TEST SUBPAGE\",
\"description\": \"TEST DESCRIPTION SUBPAGE\",
\"image\": \"https://test/static/images/test.png\",
\"css\": [],
\"lang\":\"en\",
\"js\": [],
\"url_slug\": \"subpage\"
},
\"body\": [
{
\"layout\": {
\"display\": \"flex\",
\"padding\": \"20px\"
},
\"contents\": [
{
\"tag\": \"h1\",
\"text\": \"testing subpage\"
}
]
}
],
\"sub_pages\": [
{
\"template_name\": \"TEST TEMPLATE\",
\"metadata\": {
\"title\": \"TEST NESTTED\",
\"description\": \"TEST DESCRIPTION NESTED\",
\"image\": \"https://test/static/images/test.png\",
\"css\": [],
\"js\": [],
\"url_slug\": \"nested\",
\"lang\":\"en\"
},
\"body\": [
{
\"layout\": {
\"display\": \"flex\",
\"padding\": \"20px\"
},
\"contents\": [
{
\"tag\": \"h1\",
\"text\": \"testing nested\"
}
]
}
]
}
]
}
]
},
\"sub_pages\": [
\"assets_index\": {
\"images\": [],
\"sounds\": [],
\"videos\": [],
\"docs\": [],
\"source_code\": []
},
\"templates\": [
{
\"page_data\": {
\"title\": \"A sub page\",
\"slug\": \"subpage\",
\"lang\": \"en\",
\"description\": \"A sub page of the testing web site\",
\"html_body\": \"<h1>A sub page</h1>\"
\"name\": \"TEST TEMPLATE\",
\"layout\": {
\"display\": \"grid\"
},
\"sub_pages\": [
\"contents\": [
{
\"tag\": \"nav\",
\"contents\": []
},
{
\"page_data\": {
\"title\": \"Nested page\",
\"lang\": \"en\",
\"slug\": \"nested\",
\"description\": \"Nested testing page\",
\"html_body\": \"<h1>Nested page</h1>\"
}
\"tag\": \"footer\",
\"contents\": []
}
]
}
......
......@@ -35,13 +35,17 @@ impl HtmlDoc {
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();
let placeholder = placeholder[1..placeholder.len() - 1].to_owned(); // strip the brackets
page.text_from_key(placeholder)
})
.to_string();
HtmlDoc(html)
}
pub fn empty() -> Self {
HtmlDoc(String::new())
}
}
impl std::fmt::Display for HtmlDoc {
......
......@@ -8,10 +8,104 @@ pub struct Item {
}
impl std::fmt::Display for Item {
fn fmt(&self, _f: &mut std::fmt::Formatter) -> std::fmt::Result {
unimplemented!()
fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
write!(
f,
"{}",
self.contents
.iter()
.map(|ic| ic.to_string())
.collect::<Vec<String>>()
.join("")
)
}
}
#[derive(Debug, Serialize, Deserialize, Clone)]
pub struct ItemContent {}
pub struct ItemContent {
tag: String,
text: Option<String>,
contents: Option<Vec<ItemContent>>,
}
impl std::fmt::Display for ItemContent {
fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
let body = match &self.contents {
Some(contents) => contents
.iter()
.map(|item| item.to_string())
.collect::<Vec<String>>()
.join(""),
None => self
.text
.as_ref()
.expect("Either contents or text field must be provided")
.to_string(),
};
write!(f, "<{}>{}</{}>", self.tag, body, self.tag)
}
}
#[cfg(test)]
mod test_items {
use super::*;
use std::collections::HashMap;
#[test]
fn text_item_content_to_string() {
let item_content = ItemContent {
tag: String::from("p"),
text: Some(String::from("Hello")),
contents: None,
};
assert_eq!(item_content.to_string(), "<p>Hello</p>")
}
#[test]
fn complex_item_content_to_string() {
let item_content = ItemContent {
tag: String::from("p"),
text: None,
contents: Some(vec![
ItemContent {
tag: String::from("span"),
text: Some(String::from("Hello ")),
contents: None,
},
ItemContent {
tag: String::from("b"),
text: Some(String::from("World")),
contents: None,
},
]),
};
assert_eq!(
item_content.to_string(),
"<p><span>Hello </span><b>World</b></p>"
)
}
#[test]
fn item_to_string() {
let item = Item {
layout: StyleSheet(HashMap::new()),
contents: vec![
ItemContent {
tag: String::from("span"),
text: Some(String::from("Hello ")),
contents: None,
},
ItemContent {
tag: String::from("b"),
text: Some(String::from("World")),
contents: None,
},
],
};
assert_eq!(item.to_string(), "<span>Hello </span><b>World</b>")
}
}
......@@ -5,18 +5,21 @@ use serde::{Deserialize, Serialize};
#[derive(Debug, Serialize, Deserialize, Clone)]
pub struct Page {
template: PageTemplate,
body: PageBody,
pub template_name: String,
pub body: PageBody,
pub metadata: PageMetadata,
#[serde(default = "Vec::new")]
pub sub_pages: Vec<Page>,
#[serde(default = "HtmlDoc::empty")]
pub html: HtmlDoc,
pub template: Option<PageTemplate>,
}
#[derive(Debug, Serialize, Deserialize, Clone)]
pub struct PageTemplate {
layout: StyleSheet,
name: String,
fixed_contents: Vec<ItemContent>,
pub layout: StyleSheet,
pub name: String,
pub contents: Vec<ItemContent>,
}
#[derive(Debug, Serialize, Deserialize, Clone)]
......@@ -43,8 +46,8 @@ pub struct PageMetadata {
pub lang: String,
pub description: String,
pub url_slug: String,
pub css_src: Vec<String>,
pub js_src: Vec<String>,
pub css: Vec<String>,
pub js: Vec<String>,
}
impl Page {
......@@ -52,6 +55,12 @@ impl Page {
self.html = HtmlDoc::from_page(self);
}
pub fn build_body_template(&mut self, template: &PageTemplate) {
self.template = Some(template.clone());
// TODO concat template with page body (template should have a page body placeholder)
unimplemented!()
}
pub fn text_from_key(&self, key: String) -> String {
match &key[..] {
"title" => self.metadata.title.to_owned(),
......@@ -59,8 +68,8 @@ impl Page {
"description" => self.metadata.description.to_owned(),
"slug" => self.metadata.url_slug.to_owned(),
"body" => self.body.to_string(),
// "css" => self.css_src.as_ref().unwrap_or(&String::new()).to_owned(),
// "js" => self.js_src.as_ref().unwrap_or(&String::new()).to_owned(),
// "css" => self.css.as_ref().unwrap_or(&String::new()).to_owned(),
// "js" => self.js.as_ref().unwrap_or(&String::new()).to_owned(),
_ => String::new(),
}
}
......
......@@ -7,19 +7,41 @@ use std::path::PathBuf;
#[derive(Debug, Serialize, Deserialize, Clone)]
pub struct WebSite {
root_page: Page,
assets_index: Vec<String>,
assets_index: AssetsIndex,
templates: Vec<PageTemplate>,
#[serde(default = "HashMap::new")]
pages_index: HashMap<PathBuf, Page>,
}
#[derive(Debug, Serialize, Deserialize, Clone)]
pub struct AssetsIndex {
pub images: Vec<String>,
pub sounds: Vec<String>,
pub videos: Vec<String>,
pub docs: Vec<String>,
pub source_code: Vec<String>,
}
impl WebSite {
pub fn from_json(json: &str) -> Self {
let mut obj: Self = serde_json::from_str(json).unwrap();
obj.build_assets_index();
obj.build_pages_index(obj.root_page.clone(), PathBuf::from("/"));
obj.root_page.build_html();
obj.root_page.build_body_template(
obj.templates
.iter()
.find(|t| t.name == obj.root_page.template_name)
.expect("Page template not found"),
);
for p in obj.root_page.sub_pages.iter_mut() {
p.build_html();
p.build_body_template(
obj.templates
.iter()
.find(|t| t.name == p.template_name)
.expect("Page template not found"),
);
}
obj
}
......@@ -47,7 +69,7 @@ impl WebSite {
}
fn build_assets_index(&mut self) {
unimplemented!();
return;
}
pub fn get_page_by_url(&self, url: &PathBuf) -> Option<&Page> {
......@@ -55,27 +77,27 @@ impl WebSite {
}
}
// #[cfg(test)]
// mod test_website {
// use super::*;
// use crate::testing::TEST_JSON_WEBSITE;
#[cfg(test)]
mod test_website {
use super::*;
use crate::testing::TEST_JSON_WEBSITE;
// #[test]
// fn test_index_pages_by_slug() {
// let website = WebSite::from_json(TEST_JSON_WEBSITE);
// 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>");
#[test]
fn test_index_pages_by_slug() {
let website = WebSite::from_json(TEST_JSON_WEBSITE);
let root_page = website.get_page_by_url(&PathBuf::from("/"));
assert!(root_page.is_some());
let root_page = root_page.unwrap();
assert_eq!(format!("{}", root_page.body), "<h1>testing</h1>");
// 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>");
let sub_page = website.get_page_by_url(&PathBuf::from("subpage"));
assert!(sub_page.is_some());
let sub_page = sub_page.unwrap();
assert_eq!(format!("{}", sub_page.body), "<h1>testing subpage</h1>");
// let nested_page = website.get_page_by_url(&PathBuf::from("subpage/nested"));
// assert!(nested_page.is_some());
// let nested_page = nested_page.unwrap();
// assert_eq!(nested_page.page_data.html_body, "<h1>Nested page</h1>");
// }
// }
let nested_page = website.get_page_by_url(&PathBuf::from("subpage/nested"));
assert!(nested_page.is_some());
let nested_page = nested_page.unwrap();
assert_eq!(format!("{}", nested_page.body), "<h1>testing nested</h1>");
}
}
{
"page_data": {
"title": "New Website",
"lang": "en",
"slug": "",
"description": "A new website",
"html_body": "<h1>New Website</h1>"
"root_page": {
"template_name": "basic",
"metadata": {
"title": "New Website",
"description": "A new website",
"image": "",
"css": [],
"js": [],
"url_slug": ""
},
"body": [
{
"layout": {},
"contents": [
{
"tag": "h1",
"text": "New website"
}
]
}
]
},
"sub_pages": []
"templates": [
{
"name": "basic",
"layout": {},
"contents": [
{
"tag": "nav",
"contents": []
},
{
"tag": "footer",
"contents": []
}
]
}
]
}
\ 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