add: markdown docs directory
This commit is contained in:
parent
b31d8c38b9
commit
a167da017e
8 changed files with 69 additions and 6 deletions
|
@ -34,6 +34,8 @@ In the directory you're running Tetratto from, you should create a `tetratto.tom
|
|||
|
||||
Tetratto **requires** Cloudflare Turnstile for registrations. Testing keys are listed [here](https://developers.cloudflare.com/turnstile/troubleshooting/testing/). You can _technically_ disable the captcha by using the always passing, invisible keys.
|
||||
|
||||
A `docs` directory will be generated in the same directory that you ran the `tetratto` binary in. **Markdown** files placed here will be served at `/doc/{*file_name}`. For other types of assets, you can place them in the generated `public` directory. This directory serves everything at `/public/{*file_name}`.
|
||||
|
||||
## Usage (as a user)
|
||||
|
||||
Tetratto is very simple once you get the hang of it! At the top of the page (or bottom if you're on mobile), you'll see the navigation bar. Once logged in, you'll be able to access "Home", "Popular", and "Communities" from there! You can also press your profile picture (on the right) to view your own profile, settings, or log out!
|
||||
|
|
|
@ -34,6 +34,7 @@ pub const COMPONENTS: &str = include_str!("./public/html/components.html");
|
|||
pub const MISC_INDEX: &str = include_str!("./public/html/misc/index.html");
|
||||
pub const MISC_ERROR: &str = include_str!("./public/html/misc/error.html");
|
||||
pub const MISC_NOTIFICATIONS: &str = include_str!("./public/html/misc/notifications.html");
|
||||
pub const MISC_MARKDOWN: &str = include_str!("./public/html/misc/markdown.html");
|
||||
|
||||
pub const AUTH_BASE: &str = include_str!("./public/html/auth/base.html");
|
||||
pub const AUTH_LOGIN: &str = include_str!("./public/html/auth/login.html");
|
||||
|
@ -159,6 +160,7 @@ pub(crate) async fn write_assets(config: &Config) -> PathBufD {
|
|||
write_template!(html_path->"misc/index.html"(crate::assets::MISC_INDEX) -d "misc" --config=config);
|
||||
write_template!(html_path->"misc/error.html"(crate::assets::MISC_ERROR) --config=config);
|
||||
write_template!(html_path->"misc/notifications.html"(crate::assets::MISC_NOTIFICATIONS) --config=config);
|
||||
write_template!(html_path->"misc/markdown.html"(crate::assets::MISC_MARKDOWN) --config=config);
|
||||
|
||||
write_template!(html_path->"auth/base.html"(crate::assets::AUTH_BASE) -d "auth" --config=config);
|
||||
write_template!(html_path->"auth/login.html"(crate::assets::AUTH_LOGIN) --config=config);
|
||||
|
@ -191,6 +193,7 @@ pub(crate) async fn write_assets(config: &Config) -> PathBufD {
|
|||
/// Set up extra directories.
|
||||
pub(crate) async fn init_dirs(config: &Config) {
|
||||
create_dir_if_not_exists!(&config.dirs.templates);
|
||||
create_dir_if_not_exists!(&config.dirs.docs);
|
||||
|
||||
// images
|
||||
create_dir_if_not_exists!(&config.dirs.media);
|
||||
|
|
16
crates/app/src/public/html/misc/markdown.html
Normal file
16
crates/app/src/public/html/misc/markdown.html
Normal file
|
@ -0,0 +1,16 @@
|
|||
{% import "macros.html" as macros %} {% extends "root.html" %} {% block head %}
|
||||
<title>{{ file_name }} - {{ config.name }}</title>
|
||||
{% endblock %} {% block body %} {{ macros::nav(selected="notifications") }}
|
||||
<main class="flex flex-col gap-2">
|
||||
<div class="card-nest">
|
||||
<div class="card small flex items-center justify-between gap-2">
|
||||
<span class="flex items-center gap-2">
|
||||
{{ icon "scroll-text" }}
|
||||
<span>{{ file_name }}</span>
|
||||
</span>
|
||||
</div>
|
||||
|
||||
<div class="card">{{ file|markdown|safe }}</div>
|
||||
</div>
|
||||
</main>
|
||||
{% endblock %}
|
|
@ -1,12 +1,14 @@
|
|||
use super::{PaginatedQuery, render_error};
|
||||
use crate::{State, assets::initial_context, get_lang, get_user_from_token};
|
||||
use axum::{
|
||||
Extension,
|
||||
extract::Query,
|
||||
extract::{Path, Query},
|
||||
response::{Html, IntoResponse},
|
||||
Extension,
|
||||
};
|
||||
use axum_extra::extract::CookieJar;
|
||||
use tetratto_core::model::Error;
|
||||
use std::fs::read_to_string;
|
||||
use pathbufd::PathBufD;
|
||||
|
||||
pub async fn not_found(jar: CookieJar, Extension(data): Extension<State>) -> impl IntoResponse {
|
||||
let data = data.read().await;
|
||||
|
@ -112,3 +114,37 @@ pub async fn notifications_request(
|
|||
data.1.render("misc/notifications.html", &context).unwrap(),
|
||||
))
|
||||
}
|
||||
|
||||
/// `/doc/{file_name}`
|
||||
pub async fn markdown_document_request(
|
||||
jar: CookieJar,
|
||||
Extension(data): Extension<State>,
|
||||
Path(name): Path<String>,
|
||||
) -> impl IntoResponse {
|
||||
let data = data.read().await;
|
||||
let user = get_user_from_token!(jar, data.0);
|
||||
|
||||
if name.contains("//") | name.contains("..") | name.starts_with("/") {
|
||||
return Err(Html(
|
||||
render_error(Error::NotAllowed, &jar, &data, &user).await,
|
||||
));
|
||||
}
|
||||
|
||||
let path = PathBufD::current().extend(&[&data.0.0.dirs.docs, &name]);
|
||||
let file = match read_to_string(&path) {
|
||||
Ok(f) => f,
|
||||
Err(e) => {
|
||||
return Err(Html(
|
||||
render_error(Error::MiscError(e.to_string()), &jar, &data, &user).await,
|
||||
));
|
||||
}
|
||||
};
|
||||
|
||||
let lang = get_lang!(jar, data.0);
|
||||
let mut context = initial_context(&data.0.0, lang, &user).await;
|
||||
context.insert("file", &file);
|
||||
context.insert("file_name", &name);
|
||||
|
||||
// return
|
||||
Ok(Html(data.1.render("misc/markdown.html", &context).unwrap()))
|
||||
}
|
||||
|
|
|
@ -20,6 +20,7 @@ pub fn routes() -> Router {
|
|||
.route("/", get(misc::index_request))
|
||||
.route("/popular", get(misc::popular_request))
|
||||
.route("/notifs", get(misc::notifications_request))
|
||||
.route("/doc/{*file_name}", get(misc::markdown_document_request))
|
||||
.fallback_service(get(misc::not_found))
|
||||
// mod
|
||||
.route("/mod_panel/audit_log", get(mod_panel::audit_log_request))
|
||||
|
|
|
@ -46,6 +46,9 @@ pub struct DirsConfig {
|
|||
/// The icons files directory.
|
||||
#[serde(default = "default_dir_icons")]
|
||||
pub icons: String,
|
||||
/// The markdown document files directory.
|
||||
#[serde(default = "default_dir_docs")]
|
||||
pub docs: String,
|
||||
}
|
||||
|
||||
fn default_dir_templates() -> String {
|
||||
|
@ -64,6 +67,10 @@ fn default_dir_icons() -> String {
|
|||
"icons".to_string()
|
||||
}
|
||||
|
||||
fn default_dir_docs() -> String {
|
||||
"docs".to_string()
|
||||
}
|
||||
|
||||
impl Default for DirsConfig {
|
||||
fn default() -> Self {
|
||||
Self {
|
||||
|
@ -71,6 +78,7 @@ impl Default for DirsConfig {
|
|||
assets: default_dir_assets(),
|
||||
media: default_dir_media(),
|
||||
icons: default_dir_icons(),
|
||||
docs: default_dir_docs(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
5
example/.gitignore
vendored
5
example/.gitignore
vendored
|
@ -1,11 +1,8 @@
|
|||
atto.db*
|
||||
|
||||
html/*
|
||||
!html/.gitkeep
|
||||
|
||||
public/*
|
||||
!public/.gitkeep
|
||||
|
||||
media/*
|
||||
icons/*
|
||||
langs/*
|
||||
docs/*
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue