diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/components/app.rs | 133 | ||||
-rw-r--r-- | src/components/editor/mod.rs | 25 | ||||
-rw-r--r-- | src/components/layout/mod.rs | 56 | ||||
-rw-r--r-- | src/components/mod.rs | 12 | ||||
-rw-r--r-- | src/components/renderer/mod.rs | 23 | ||||
-rw-r--r-- | src/data/config.rs | 1 | ||||
-rw-r--r-- | src/data/mod.rs | 8 | ||||
-rw-r--r-- | src/data/namespace.rs | 5 | ||||
-rw-r--r-- | src/data/page.rs | 2 | ||||
-rw-r--r-- | src/lib.rs | 11 | ||||
-rw-r--r-- | src/main.rs | 77 | ||||
-rw-r--r-- | src/routes/mod.rs | 17 |
12 files changed, 103 insertions, 267 deletions
diff --git a/src/components/app.rs b/src/components/app.rs deleted file mode 100644 index 2814562..0000000 --- a/src/components/app.rs +++ /dev/null @@ -1,133 +0,0 @@ -use std::collections::HashMap; - -use leptos::prelude::*; -use leptos::Params; -use leptos_meta::{provide_meta_context, MetaTags, Stylesheet, Title}; -use leptos_router::hooks::use_params; -use leptos_router::params::Params; -use leptos_router::{ - components::{ParentRoute, Route, Router, Routes}, - path, -}; - -use super::editor::WikiEditor; -use super::renderer::WikiPage; -use crate::components::layout::Layout; -use crate::data::{Namespace, Page, PageData, PageUuid}; - -pub fn shell(options: LeptosOptions) -> impl IntoView { - view! { - <!DOCTYPE html> - <html lang="en"> - <head> - <meta charset="utf-8"/> - <meta name="viewport" content="width=device-width, initial-scale=1"/> - <AutoReload options=options.clone() /> - <HydrationScripts options islands=true/> - <MetaTags/> - </head> - <body> - <App/> - </body> - </html> - } -} - -#[component] -pub fn App() -> impl IntoView { - // Provides context that manages stylesheets, titles, meta tags, etc. - provide_meta_context(); - - view! { - // injects a stylesheet into the document <head> - // id=leptos means cargo-leptos will hot-reload this stylesheet - <Stylesheet id="leptos" href="/_/stormscribe.css"/> - - // sets the document title - <Title text="Welcome to Leptos"/> - - // content for this welcome page - <Router> - <Routes fallback=|| "Page not found.".into_view()> - <ParentRoute path=path!("/") view=Layout> - <Route path=path!("/~/*path") view=PageRender/> - <Route path=path!("/edit/*path") view=PageEdit/> - </ParentRoute> - </Routes> - </Router> - } -} - -#[derive(Params, PartialEq)] -struct PageParams { - path: Option<String>, -} - -#[server] -async fn get_namespace() -> Result<Namespace, ServerFnError> { - use crate::data::StormscribeData; - - Ok(StormscribeData::get_namespace().await) -} - -#[server] -async fn get_pages() -> Result<HashMap<PageUuid, Page>, ServerFnError> { - use crate::data::StormscribeData; - - Ok(StormscribeData::get_all_pages().await) -} - -#[server] -async fn lookup_page(path: String) -> Result<PageData, ServerFnError> { - use crate::data::StormscribeData; - - Ok(StormscribeData::get_page_data(path).await) -} - -// Renders a page -#[component] -fn PageRender() -> impl IntoView { - let params = use_params::<PageParams>(); - - let page_path = params - .read() - .as_ref() - .ok() - .map(|params| params.path.clone().unwrap_or("Unknown path".to_string())) - .unwrap_or("Could not read params".to_string()); - - let page_resource = Resource::new( - move || page_path.clone(), - |page_path| async move { lookup_page(page_path).await }, - ); - - view! { - <Suspense - fallback=move || view! { <p>"Loading..."</p> } - > - {move || page_resource.get() - .map(|page| view! { - <pre>{format!("{page:#?}")}</pre> - }) - } - </Suspense> - } - .into_any() -} - -// Renders a page -#[component] -fn PageEdit() -> impl IntoView { - let params = use_params::<PageParams>(); - - let page_path = params - .read() - .as_ref() - .ok() - .map(|params| params.path.clone().unwrap_or("Unknown path".to_string())) - .unwrap_or("Could not read params".to_string()); - - view! { - <WikiEditor url_path=page_path /> - } -} diff --git a/src/components/editor/mod.rs b/src/components/editor/mod.rs index 05e45d3..4d38c69 100644 --- a/src/components/editor/mod.rs +++ b/src/components/editor/mod.rs @@ -1,13 +1,18 @@ -use leptos::prelude::*; -use leptos::{island, view, IntoView}; +use std::path::PathBuf; +use morgana::{morx, Component, RenderNode}; -#[island] -pub fn WikiEditor( - url_path: String, -) -> impl IntoView { - view! { - <h1>Article (Editing)</h1> - <p>Page render</p> - <pre>{url_path}</pre> +stylance::import_crate_style!(styles, "src/components/layout/layout.module.css"); + +pub struct Editor { + page_path: PathBuf, +} + +impl Component for Editor { + fn render(self: Box<Self>) -> RenderNode { + morx! { + h1= "Article (Editing)" + p= "Page render" + pre= {self.page_path.to_string_lossy()} + } } } diff --git a/src/components/layout/mod.rs b/src/components/layout/mod.rs index e688f5f..cc524e9 100644 --- a/src/components/layout/mod.rs +++ b/src/components/layout/mod.rs @@ -1,25 +1,41 @@ -use leptos::prelude::*; -use leptos::component; -use leptos_router::components::Outlet; +use morgana::{morx, Component, RenderNode}; stylance::import_crate_style!(styles, "src/components/layout/layout.module.css"); -#[component] -pub fn Layout() -> impl IntoView { - view! { - <div class=styles::layout> - <header> - <a href="/" id="siteTitle">Site Title</a> - </header> - <nav> - <p>Nav</p> - </nav> - <main> - <Outlet/> - </main> - <footer> - <p>Footer</p> - </footer> - </div> +pub struct Layout { + pub children: Vec<RenderNode>, + pub page_title: String, + pub site_title: String, +} + +impl Component for Layout { + fn render(self: Box<Self>) -> RenderNode { + morx! { + html lang="html" { + head { + title ={self.page_title} + } + body { + div class={styles::layout} { + header { + a href="/" id="siteTitle" { + ={self.site_title} + } + } + + nav { + p= "Nav" + } + + main ={self.children} + + footer { + p= "Footer" + } + } + } + } + } } } + diff --git a/src/components/mod.rs b/src/components/mod.rs index 2015a2e..1058018 100644 --- a/src/components/mod.rs +++ b/src/components/mod.rs @@ -1,7 +1,7 @@ -pub mod editor; -pub mod layout; -pub mod renderer; +mod editor; +mod layout; +mod renderer; -pub mod app; - -pub use app::App; +pub use editor::Editor; +pub use renderer::PageRenderer; +pub use layout::Layout; diff --git a/src/components/renderer/mod.rs b/src/components/renderer/mod.rs index 5a30c2e..e790924 100644 --- a/src/components/renderer/mod.rs +++ b/src/components/renderer/mod.rs @@ -1,12 +1,17 @@ -use leptos::prelude::*; -use leptos::{component, view, IntoView}; +use std::path::PathBuf; +use morgana::{morx, Component, RenderNode}; -#[component] -pub fn WikiPage(// page_data: Page, - // parent_namespaces: Vec<Namespace> -) -> impl IntoView { - view! { - <h1>Article (Viewing)</h1> - <p>Page render</p> +stylance::import_crate_style!(styles, "src/components/layout/layout.module.css"); + +pub struct PageRenderer { + page_path: PathBuf, +} + +impl Component for PageRenderer { + fn render(self: Box<Self>) -> RenderNode { + morx! { + h1= "Article (Viewing)" + p= "Page render" + } } } diff --git a/src/data/config.rs b/src/data/config.rs index 11e10cc..34ec958 100644 --- a/src/data/config.rs +++ b/src/data/config.rs @@ -20,7 +20,6 @@ pub struct Config { pub footer_copyright: Option<String>, } -#[cfg(feature = "ssr")] impl Config { pub fn read_from_file() -> Result<Self, String> { let config_path = Self::get_location()?; diff --git a/src/data/mod.rs b/src/data/mod.rs index 1465fee..2be1f0a 100644 --- a/src/data/mod.rs +++ b/src/data/mod.rs @@ -1,13 +1,9 @@ use serde::{Deserialize, Serialize}; -#[cfg(feature = "ssr")] use tokio::sync::Mutex; use uuid::Uuid; -#[cfg(feature = "ssr")] use fs2::FileExt; -#[cfg(feature = "ssr")] use std::fs::File; -#[cfg(feature = "ssr")] use std::sync::LazyLock; use std::{collections::HashMap, path::Path, sync::Arc}; @@ -23,11 +19,9 @@ pub use page::{Page, Pages}; #[derive(Hash, PartialEq, Eq, Clone, Debug, Deserialize, Serialize)] pub struct PageUuid(Uuid); -#[cfg(feature = "ssr")] pub static CONFIG: LazyLock<Config> = LazyLock::new(|| Config::read_from_file().expect("Could not open config file")); -#[cfg(feature = "ssr")] static DATA_LOCK: LazyLock<StormscribeData> = LazyLock::new(|| { let config = &CONFIG; let lock_path = Path::join(&config.data_dir, ".lock"); @@ -53,7 +47,6 @@ static DATA_LOCK: LazyLock<StormscribeData> = LazyLock::new(|| { } }); -#[cfg(feature = "ssr")] pub struct StormscribeData { file_lock: File, data_snapshot: Mutex<Arc<DataSnapshot>>, @@ -71,7 +64,6 @@ pub struct PageData { content: String, } -#[cfg(feature = "ssr")] impl StormscribeData { async fn get_snapshot() -> Arc<DataSnapshot> { DATA_LOCK.data_snapshot.lock().await.clone() diff --git a/src/data/namespace.rs b/src/data/namespace.rs index 4aa0419..4347abb 100644 --- a/src/data/namespace.rs +++ b/src/data/namespace.rs @@ -1,15 +1,13 @@ -use serde::{Deserialize, Serialize}; use std::collections::HashMap; use uuid::Uuid; use crate::data::PageUuid; -#[cfg(feature = "ssr")] use std::{ fs, path::{Path, PathBuf}, }; -#[derive(Clone, Debug, Serialize, Deserialize)] +#[derive(Clone, Debug)] pub struct Namespace { pub page: Option<PageUuid>, pub children: HashMap<String, Namespace>, @@ -28,7 +26,6 @@ impl Namespace { } } -#[cfg(feature = "ssr")] impl Namespaces { pub fn init(namespaces_dir: &Path) -> Result<Self, String> { // Read dir recursive diff --git a/src/data/page.rs b/src/data/page.rs index 7b7d432..4a31894 100644 --- a/src/data/page.rs +++ b/src/data/page.rs @@ -28,7 +28,6 @@ pub struct Pages { const METADATA_DIVIDER: &'static str = "<!-- trans rights ~ath&+ -->"; -#[cfg(feature = "ssr")] impl Pages { pub fn init(pages_dir: &Path) -> Result<Self, String> { // Read dir @@ -152,7 +151,6 @@ impl Pages { } } -#[cfg(feature = "ssr")] impl Page { pub async fn read_content(&self) -> Result<String, String> { use std::io::Read; diff --git a/src/lib.rs b/src/lib.rs deleted file mode 100644 index 955e795..0000000 --- a/src/lib.rs +++ /dev/null @@ -1,11 +0,0 @@ -pub mod components; -pub mod data; - -#[cfg(feature = "hydrate")] -#[wasm_bindgen::prelude::wasm_bindgen] -pub fn hydrate() { - use crate::components::app::*; - - console_error_panic_hook::set_once(); - leptos::mount::hydrate_islands(); -} diff --git a/src/main.rs b/src/main.rs index 8cffc27..b358bb6 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,66 +1,17 @@ -#[cfg(feature = "ssr")] -#[tokio::main] -async fn main() { - use axum::{response::Redirect, routing::get, Router}; - use leptos::logging::log; - use leptos::prelude::*; - use leptos_axum::{generate_route_list, LeptosRoutes}; - use stormscribe::components::app::*; - let conf = get_configuration(None).unwrap(); - let addr = conf.leptos_options.site_addr; - let leptos_options = conf.leptos_options; - // Generate the list of routes in your Leptos App - let routes = generate_route_list(App); - - let app = Router::new() - .route("/", get(|| async { Redirect::temporary("/~/") })) - .leptos_routes(&leptos_options, routes, { - let leptos_options = leptos_options.clone(); - move || shell(leptos_options.clone()) - }) - .fallback(leptos_axum::file_and_error_handler(shell)) - .with_state(leptos_options); - - // run our app with hyper - // `axum::Server` is a re-export of `hyper::Server` - log!("listening on http://{}", &addr); - let listener = tokio::net::TcpListener::bind(&addr).await.unwrap(); - axum::serve(listener, app.into_make_service()) - .with_graceful_shutdown(shutdown_signal()) - .await - .unwrap(); -} - -#[cfg(feature = "ssr")] -async fn shutdown_signal() { - use tokio::signal; - let ctrl_c = async { - signal::ctrl_c() - .await - .expect("could not install SIGINT handler") - }; - - #[cfg(unix)] - let terminate = async { - signal::unix::signal(signal::unix::SignalKind::terminate()) - .expect("could not install SIGTERM handler") - .recv() - .await; - }; - - #[cfg(not(unix))] - let terminate = std::future::pending::<()>(); - - tokio::select! { - _ = ctrl_c => {}, - _ = terminate => {}, - } +#[macro_use] extern crate rocket; +use rocket::fs::{FileServer, relative}; +mod data; +mod components; +mod routes; + +#[launch] +async fn stormscribe() -> _ { + rocket::build() + .mount("/", FileServer::from(relative!("./public")).rank(-10)) + .mount("/", routes![ + routes::render_page, + routes::render_editor, + ]) } -#[cfg(not(feature = "ssr"))] -pub fn main() { - // no client-side main function - // unless we want this to work with e.g., Trunk for pure client-side testing - // see lib.rs for hydration function instead -} diff --git a/src/routes/mod.rs b/src/routes/mod.rs new file mode 100644 index 0000000..935bab0 --- /dev/null +++ b/src/routes/mod.rs @@ -0,0 +1,17 @@ +use std::path::PathBuf; + +use morgana::{morx, render_tree_blocking}; +use rocket::response::content::RawHtml; +use crate::components::{Layout}; + +#[get("/<page_path..>")] +pub fn render_page(page_path: PathBuf) -> RawHtml<String> { + RawHtml(render_tree_blocking(morx! { + Layout page_title="Test page" site_title="Stormscribe" + })) +} + +#[get("/<page_path..>?edit")] +pub fn render_editor(page_path: PathBuf) -> String { + "not implemented".to_string() +} |