add: allow lisp templates (bberry)

This commit is contained in:
trisua 2025-05-30 21:22:53 -04:00
parent 8de5c0ea76
commit 78d0766345
10 changed files with 296 additions and 263 deletions

421
Cargo.lock generated

File diff suppressed because it is too large Load diff

View file

@ -17,7 +17,7 @@ tracing = "0.1.41"
tracing-subscriber = { version = "0.3.19", features = ["env-filter"] } tracing-subscriber = { version = "0.3.19", features = ["env-filter"] }
tower-http = { version = "0.6.4", features = ["trace", "fs", "catch-panic"] } tower-http = { version = "0.6.4", features = ["trace", "fs", "catch-panic"] }
axum = { version = "0.8.4", features = ["macros", "ws"] } axum = { version = "0.8.4", features = ["macros", "ws"] }
tokio = { version = "1.45.0", features = ["macros", "rt-multi-thread"] } tokio = { version = "1.45.1", features = ["macros", "rt-multi-thread"] }
axum-extra = { version = "0.10.1", features = ["cookie", "multipart"] } axum-extra = { version = "0.10.1", features = ["cookie", "multipart"] }
ammonia = "4.1.0" ammonia = "4.1.0"
tetratto-shared = { path = "../shared" } tetratto-shared = { path = "../shared" }
@ -27,7 +27,7 @@ tetratto-core = { path = "../core", features = [
tetratto-l10n = { path = "../l10n" } tetratto-l10n = { path = "../l10n" }
image = "0.25.6" image = "0.25.6"
reqwest = { version = "0.12.15", features = ["json", "stream"] } reqwest = { version = "0.12.18", features = ["json", "stream"] }
regex = "1.11.1" regex = "1.11.1"
serde_json = "1.0.140" serde_json = "1.0.140"
mime_guess = "2.0.5" mime_guess = "2.0.5"
@ -48,3 +48,4 @@ async-stripe = { version = "0.41.0", features = [
] } ] }
emojis = "0.6.4" emojis = "0.6.4"
webp = "0.3.0" webp = "0.3.0"
bberry = "0.1.1"

View file

@ -1,3 +1,4 @@
use bberry::core::element::Render;
use pathbufd::PathBufD; use pathbufd::PathBufD;
use regex::Regex; use regex::Regex;
use std::{ use std::{
@ -39,9 +40,9 @@ pub const ROOT: &str = include_str!("./public/html/root.html");
pub const MACROS: &str = include_str!("./public/html/macros.html"); pub const MACROS: &str = include_str!("./public/html/macros.html");
pub const COMPONENTS: &str = include_str!("./public/html/components.html"); pub const COMPONENTS: &str = include_str!("./public/html/components.html");
pub const MISC_ERROR: &str = include_str!("./public/html/misc/error.html"); pub const MISC_ERROR: &str = include_str!("./public/html/misc/error.lisp");
pub const MISC_NOTIFICATIONS: &str = include_str!("./public/html/misc/notifications.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 MISC_MARKDOWN: &str = include_str!("./public/html/misc/markdown.lisp");
pub const MISC_REQUESTS: &str = include_str!("./public/html/misc/requests.html"); pub const MISC_REQUESTS: &str = include_str!("./public/html/misc/requests.html");
pub const AUTH_BASE: &str = include_str!("./public/html/auth/base.html"); pub const AUTH_BASE: &str = include_str!("./public/html/auth/base.html");
@ -161,7 +162,7 @@ macro_rules! vendor_icon {
/// * icons /// * icons
/// * icons (with class specifier) /// * icons (with class specifier)
/// * l10n text /// * l10n text
pub(crate) async fn replace_in_html(input: &str, config: &Config) -> String { pub(crate) async fn replace_in_html(input: &str, config: &Config, lisp: bool) -> String {
let reader = HTML_FOOTER.read().await; let reader = HTML_FOOTER.read().await;
if reader.is_empty() { if reader.is_empty() {
@ -180,7 +181,12 @@ pub(crate) async fn replace_in_html(input: &str, config: &Config) -> String {
let reader = HTML_FOOTER.read().await; let reader = HTML_FOOTER.read().await;
// ... // ...
let mut input = input.to_string(); let mut input = if !lisp {
input.to_string()
} else {
bberry::parse(input).0.render()
};
input = input.replace("<!-- prettier-ignore -->", ""); input = input.replace("<!-- prettier-ignore -->", "");
// l10n text // l10n text
@ -243,9 +249,9 @@ pub(crate) async fn write_assets(config: &Config) -> PathBufD {
write_template!(html_path->"macros.html"(crate::assets::MACROS) --config=config); write_template!(html_path->"macros.html"(crate::assets::MACROS) --config=config);
write_template!(html_path->"components.html"(crate::assets::COMPONENTS) --config=config); write_template!(html_path->"components.html"(crate::assets::COMPONENTS) --config=config);
write_template!(html_path->"misc/error.html"(crate::assets::MISC_ERROR) -d "misc" --config=config); write_template!(html_path->"misc/error.html"(crate::assets::MISC_ERROR) -d "misc" --config=config --lisp);
write_template!(html_path->"misc/notifications.html"(crate::assets::MISC_NOTIFICATIONS) --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->"misc/markdown.html"(crate::assets::MISC_MARKDOWN) --config=config --lisp);
write_template!(html_path->"misc/requests.html"(crate::assets::MISC_REQUESTS) --config=config); write_template!(html_path->"misc/requests.html"(crate::assets::MISC_REQUESTS) --config=config);
write_template!(html_path->"auth/base.html"(crate::assets::AUTH_BASE) -d "auth" --config=config); write_template!(html_path->"auth/base.html"(crate::assets::AUTH_BASE) -d "auth" --config=config);

View file

@ -7,7 +7,15 @@ macro_rules! write_template {
($into:ident->$path:literal($as:expr) --config=$config:ident) => { ($into:ident->$path:literal($as:expr) --config=$config:ident) => {
std::fs::write( std::fs::write(
$into.join($path), $into.join($path),
$crate::assets::replace_in_html($as, &$config).await, $crate::assets::replace_in_html($as, &$config, false).await,
)
.unwrap();
};
($into:ident->$path:literal($as:expr) --config=$config:ident --lisp) => {
std::fs::write(
$into.join($path),
$crate::assets::replace_in_html($as, &$config, true).await,
) )
.unwrap(); .unwrap();
}; };
@ -29,7 +37,20 @@ macro_rules! write_template {
std::fs::write( std::fs::write(
$into.join($path), $into.join($path),
$crate::assets::replace_in_html($as, &$config).await, $crate::assets::replace_in_html($as, &$config, false).await,
)
.unwrap();
};
($into:ident->$path:literal($as:expr) -d $dir_path:literal --config=$config:ident --lisp) => {
let dir = $into.join($dir_path);
if !std::fs::exists(&dir).unwrap() {
std::fs::create_dir(dir).unwrap();
}
std::fs::write(
$into.join($path),
$crate::assets::replace_in_html($as, &$config, true).await,
) )
.unwrap(); .unwrap();
}; };

View file

@ -1,22 +0,0 @@
{% extends "root.html" %} {% block head %}
<title>{{ error_text }} - {{ config.name }}</title>
{% endblock %} {% block body %} {{ macros::nav() }}
<main class="flex flex-col gap-2">
<div class="card-nest">
<div class="card">
<b>Error! 😦</b>
</div>
<div class="card flex flex-col gap-4">
<span>{{ error_text }}</span>
<div class="w-full flex gap-2">
<a class="button primary" href="/">Home</a>
<a class="button secondary" href="javascript:history.back()"
>Back</a
>
</div>
</div>
</div>
</main>
{% endblock %}

View file

@ -0,0 +1,26 @@
(text "{% extends \"root.html\" %} {% block head %}")
(title (text "{{ error_text }} - {{ config.name }}"))
(text "{% endblock %} {% block body %} {{ macros::nav() }}")
(main
(: "class" "flex flex-col gap-2")
(div
(: "class" "card-nest")
(div
(: "class" "card")
(b (text "Error 😦")))
(div
(: "class" "card flex flex-col gap-4")
(span (text "{{ error_text }}"))
(div
(: "class" "w-full flex gap-2")
(a
(: "class" "button primary") (: "href" "/")
(text "Home"))
(a
(: "class" "button secondary") (: "href" "javascript:history.back()")
(text "Back"))))))
(text "{% endblock %}")

View file

@ -1,16 +0,0 @@
{% extends "root.html" %} {% block head %}
<title>{{ file_name }} - {{ config.name }}</title>
{% endblock %} {% block body %} {{ macros::nav() }}
<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 %}

View file

@ -0,0 +1,20 @@
(text "{% extends \"root.html\" %} {% block head %}")
(title (text "{{ file_name }} - {{ config.name }}"))
(text "{% endblock %} {% block body %} {{ macros::nav() }}")
(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")
(text "{{ icon scroll-text }}")
(span (text "{{ file_name }}"))))
(div
(: "class" "card")
(span (text "{{ file|markdown|safe }}")))))
(text "{% endblock %}")

View file

@ -17,7 +17,7 @@ tetratto-shared = { path = "../shared" }
tetratto-l10n = { path = "../l10n" } tetratto-l10n = { path = "../l10n" }
serde_json = "1.0.140" serde_json = "1.0.140"
totp-rs = { version = "5.7.0", features = ["qr", "gen_secret"] } totp-rs = { version = "5.7.0", features = ["qr", "gen_secret"] }
reqwest = { version = "0.12.15", features = ["json"] } reqwest = { version = "0.12.18", features = ["json"] }
bitflags = "2.9.1" bitflags = "2.9.1"
async-recursion = "1.1.1" async-recursion = "1.1.1"
md-5 = "0.10.6" md-5 = "0.10.6"
@ -28,7 +28,7 @@ redis = { version = "0.31.0", features = [
"tokio-comp", "tokio-comp",
], optional = true } ], optional = true }
rusqlite = { version = "0.35.0", optional = true } rusqlite = { version = "0.36.0", optional = true }
tokio-postgres = { version = "0.7.13", optional = true } tokio-postgres = { version = "0.7.13", optional = true }
bb8-postgres = { version = "0.9.0", optional = true } bb8-postgres = { version = "0.9.0", optional = true }

View file

@ -15,4 +15,4 @@ rand = "0.9.1"
serde = "1.0.219" serde = "1.0.219"
sha2 = "0.10.9" sha2 = "0.10.9"
snowflaked = "1.0.3" snowflaked = "1.0.3"
uuid = { version = "1.16.0", features = ["v4"] } uuid = { version = "1.17.0", features = ["v4"] }