From b1ca558d8d0dd73f981916e4badcfa965573b19c Mon Sep 17 00:00:00 2001 From: CodeDoctorDE Date: Sun, 17 Dec 2023 21:00:55 +0100 Subject: [PATCH] Improve generation --- api/src/models/asset.rs | 8 +-- cli/src/directory.rs | 64 +++++++++---------- cli/src/docs.rs | 31 +++++++-- cli/src/main.rs | 9 ++- .../codedoctor/assets/testasset/config.toml | 4 ++ example/content/codedoctor/config.toml | 3 + 6 files changed, 71 insertions(+), 48 deletions(-) create mode 100644 example/content/codedoctor/assets/testasset/config.toml create mode 100644 example/content/codedoctor/config.toml diff --git a/api/src/models/asset.rs b/api/src/models/asset.rs index 95f1a05..83ccdd3 100644 --- a/api/src/models/asset.rs +++ b/api/src/models/asset.rs @@ -1,15 +1,15 @@ use serde::{Deserialize, Serialize}; use crate::models::Named; -// Path: assets/{author}/{name}/asset.toml +// Path: content/{author}/{name}/asset.toml #[derive(Debug, Serialize, Deserialize, Clone, Default)] pub struct Asset { pub author : String, pub name : String, pub id : String, pub tags : Vec, - pub thumbnail_url : String, - pub preview_urls : Vec, + pub thumbnail_url : Option, + pub preview_urls : Option>, pub current_version : Version, pub previous_versions : Vec, pub summary : Option, @@ -28,7 +28,7 @@ pub struct Version { pub blake3 : Option, } -// Path: assets/{author}/author.toml +// Path: content/{author}/author.toml #[derive(Debug, Serialize, Deserialize, Clone, Default)] pub struct Author { pub name : String, diff --git a/cli/src/directory.rs b/cli/src/directory.rs index 7811611..ff1926a 100644 --- a/cli/src/directory.rs +++ b/cli/src/directory.rs @@ -12,8 +12,8 @@ pub enum ModelError { IoError(#[from] io::Error), #[error(transparent)] TomlError(#[from] de::Error), - #[error("Model file not found")] - ModelFileNotFound, + #[error("Model file not found (expected {0:?})")] + ModelFileNotFound(Option), #[error("Model name not valid (expected {expected:?}, found {found:?})")] NotValidName { expected: Option, found: String }, } @@ -29,13 +29,17 @@ pub trait ModelDirectory fn file_path(&self) -> PathBuf { self.data_path().join("config.toml") } + fn content_path(&self) -> PathBuf { + self.data_path().join("content") + } fn name(&self) -> Option; fn model(&self) -> Result { + let file = self.file_path(); if !self.is_valid() { - return Err(ModelFileNotFound); + return Err(ModelFileNotFound(Some(file))); } - let data = std::fs::read_to_string(self.file_path())?; + let data = std::fs::read_to_string(file)?; let model: T = toml::from_str(&data)?; if self.name().map(|name| name != model.name()).unwrap_or(false) { return Err(ModelError::NotValidName { @@ -62,20 +66,27 @@ impl RepositoryDirectory { } pub fn authors(&self) -> Result, io::Error> { - let mut assets = Vec::new(); - for entry in self.data_path().read_dir()? { + let mut authors = Vec::new(); + let content = self.content_path(); + if !content.exists() { + return Ok(authors); + } + for entry in content.read_dir()? { let Ok(entry) = entry else { continue; }; + if !entry.path().is_dir() { + continue; + } let path = entry.path(); let file_name = path.file_name().unwrap().to_str().unwrap().to_string(); if path.is_dir() { - assets.push(file_name); + authors.push(file_name); } } - Ok(assets) + Ok(authors) } pub fn author(&self, name: &str) -> AuthorDirectory { @@ -98,7 +109,11 @@ pub struct AuthorDirectory<'a> (&'a RepositoryDirectory, String); impl AuthorDirectory<'_> { pub fn assets(&self) -> Result, io::Error> { let mut assets = Vec::new(); - for entry in self.data_path().read_dir()? { + let path = self.assets_path(); + if !path.exists() { + return Ok(assets); + } + for entry in path.read_dir()? { let Ok(entry) = entry else { continue; }; @@ -113,6 +128,10 @@ impl AuthorDirectory<'_> { Ok(assets) } + pub fn assets_path(&self) -> PathBuf { + self.data_path().join("assets") + } + pub fn asset(&self, name: &str) -> AssetDirectory { AssetDirectory(self, name.to_owned()) } @@ -120,7 +139,7 @@ impl AuthorDirectory<'_> { impl ModelDirectory for AuthorDirectory<'_> { fn data_path(&self) -> PathBuf { - self.0.data_path().join(&self.1) + self.0.content_path().join(&self.1) } fn name(&self) -> Option { @@ -130,32 +149,9 @@ impl ModelDirectory for AuthorDirectory<'_> { pub struct AssetDirectory<'a> (&'a AuthorDirectory<'a>, String); -impl AssetDirectory<'_> { - pub fn assets_path(&self) -> PathBuf { - self.data_path().join("assets") - } - - pub fn is_valid(&self) -> bool { - self.data_path().is_dir() - } - - pub fn get_asset_path(&self, name: &str) -> Option { - let path = self.assets_path().join(name); - // If path is file and assets_path is parent of path - if !path.is_file() || !path.starts_with(self.assets_path()) { - return None; - } - Some(path) - } - - pub fn has_asset(&self, name: &str) -> bool { - self.get_asset_path(name).is_some() - } -} - impl ModelDirectory for AssetDirectory<'_> { fn data_path(&self) -> PathBuf { - self.0.data_path().join(&self.1) + self.0.assets_path().join(&self.1) } fn name(&self) -> Option { diff --git a/cli/src/docs.rs b/cli/src/docs.rs index e121f8b..cdbe61c 100644 --- a/cli/src/docs.rs +++ b/cli/src/docs.rs @@ -1,8 +1,8 @@ -use std::{fs, path::Path, io::{self, Write}}; +use std::{fs, path::Path, io::Write}; -use handlebars::{Handlebars, TemplateError, Context}; +use handlebars::{Handlebars, TemplateError}; use luna_api::models::RepositoryData; -use serde_json::json; +use serde_json::{json, Value}; use thiserror::Error; use rust_embed::RustEmbed; @@ -31,6 +31,18 @@ pub fn generate_docs(data: &RepositoryData, output : String) -> Result<(), DocsE render_static("index", data, &hb, &output)?; render_static("search", data, &hb, &output)?; + + for author in data.authors.iter() { + fs::create_dir_all(format!("{}/{}", output, author.name))?; + } + for asset in data.assets.iter() { + let context: &Value = &json!({ + "asset": asset, + "info": data.info + }); + render_dynamic("asset", &format!("{}/{}", asset.author, asset.name), &hb, &output, context)?; + } + for file in Public::iter() { let path = file.as_ref(); let content = Public::get(path).unwrap(); @@ -47,11 +59,16 @@ pub fn generate_docs(data: &RepositoryData, output : String) -> Result<(), DocsE } fn render_static(name : &str, data: &RepositoryData, hb: &Handlebars, output : &str) -> Result<(), DocsError> { - let context = &json!({ + let context: &Value = &json!({ "info": data.info }); - let rendered = hb.render(&format!("templates/{}.hbs",name), context)?; - std::fs::write(format!("{}/{}.html", output, name), rendered)?; - println!("Rendered {} at {}/{}.html", name, output, name); + render_dynamic(name, name, hb, output, context) +} + +fn render_dynamic(name : &str, output_name : &str, hb: &Handlebars, output : &str, context: &Value) -> Result<(), DocsError> { + let rendered = hb.render(&format!("templates/{}.hbs",name), &context)?; + fs::write(format!("{}/{}.html", output, output_name), rendered)?; + println!("Rendered {} at {}/{}.html", name, output, output_name); Ok(()) + } diff --git a/cli/src/main.rs b/cli/src/main.rs index 08bdc9c..a1f02d7 100644 --- a/cli/src/main.rs +++ b/cli/src/main.rs @@ -58,10 +58,10 @@ fn main() { } fn docs(path: Option, index: Option) { - let index = index.unwrap_or(String::from("index.json")); + let index = index.unwrap_or(format!("{}/index.json", path.clone().unwrap_or(".".to_string()))); let data = RepositoryData::from_index( std::fs::read_to_string(&index) - .expect("Could not read index file") + .expect(&format!("Could not read index file {}", &index)) .as_ref(), ) .expect("Could not parse index file"); @@ -76,7 +76,10 @@ fn docs(path: Option, index: Option) { } fn generate(path: Option) { - let path = path.unwrap_or(String::from("index.json")); + if let Some(path) = &path { + std::fs::create_dir_all(&path).expect("Could not create directory"); + } + let path = format!("{}/index.json", path.unwrap_or(".".to_string())); let directory = directory::RepositoryDirectory::new(None); match { directory.generate_index() } { Ok(data) => { diff --git a/example/content/codedoctor/assets/testasset/config.toml b/example/content/codedoctor/assets/testasset/config.toml new file mode 100644 index 0000000..62b0b77 --- /dev/null +++ b/example/content/codedoctor/assets/testasset/config.toml @@ -0,0 +1,4 @@ +name = "testasset" +author = "obiwan" +id = "LEL" +tags = ["test", "asset"] \ No newline at end of file diff --git a/example/content/codedoctor/config.toml b/example/content/codedoctor/config.toml new file mode 100644 index 0000000..2e1202b --- /dev/null +++ b/example/content/codedoctor/config.toml @@ -0,0 +1,3 @@ +name = "codedoctor" +email = "codedoctor@linwood.dev" +links = ["https://github.com/CodeDoctorDE"] \ No newline at end of file