add: text and icon plugins (bberry)

This commit is contained in:
trisua 2025-05-31 13:07:34 -04:00
parent 350e47f4b7
commit 7de2c2e935
5 changed files with 78 additions and 38 deletions

4
Cargo.lock generated
View file

@ -339,9 +339,9 @@ dependencies = [
[[package]]
name = "bberry"
version = "0.1.2"
version = "0.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d73b8674872fdd2eb09463fc9e3d15c4510a3abd8a1f8ef0a9e918065913aed5"
checksum = "5ee0ee2ee1f1a6094d77ba1bf5402f8a8d66e77f6353aff728e37249b2e77458"
[[package]]
name = "bit_field"

View file

@ -48,4 +48,4 @@ async-stripe = { version = "0.41.0", features = [
] }
emojis = "0.6.4"
webp = "0.3.0"
bberry = "0.1.2"
bberry = "0.2.0"

View file

@ -1,4 +1,7 @@
use bberry::core::element::Render;
use bberry::{
core::element::{Element, Render},
text, read_param,
};
use pathbufd::PathBufD;
use regex::Regex;
use std::{
@ -168,7 +171,12 @@ macro_rules! vendor_icon {
/// * icons
/// * icons (with class specifier)
/// * l10n text
pub(crate) async fn replace_in_html(input: &str, config: &Config, lisp: bool) -> String {
pub(crate) async fn replace_in_html(
input: &str,
config: &Config,
lisp: bool,
plugins: Option<&mut HashMap<String, Box<dyn FnMut(Element) -> Element>>>,
) -> String {
let reader = HTML_FOOTER.read().await;
if reader.is_empty() {
@ -190,7 +198,11 @@ pub(crate) async fn replace_in_html(input: &str, config: &Config, lisp: bool) ->
let mut input = if !lisp {
input.to_string()
} else {
bberry::parse(input).0.render()
if let Some(plugins) = plugins {
bberry::parse(input).render(plugins)
} else {
bberry::parse(input).render_safe()
}
};
input = input.replace("<!-- prettier-ignore -->", "");
@ -243,21 +255,49 @@ pub(crate) async fn replace_in_html(input: &str, config: &Config, lisp: bool) ->
input
}
pub(crate) fn lisp_plugins() -> HashMap<String, Box<dyn FnMut(Element) -> Element>> {
let mut plugins = HashMap::new();
plugins.insert(
"icon".to_string(),
Box::new(|e: Element| text!(format!("{{{{ icon \"{}\" }}}}", read_param!(e, 0)))) as _,
);
plugins.insert(
"icon_class".to_string(),
Box::new(|e: Element| {
text!(format!(
"{{{{ icon \"{}\" c({}) }}}}",
read_param!(e, 0),
read_param!(e, 1)
))
}) as _,
);
plugins.insert(
"str".to_string(),
Box::new(|e: Element| text!(format!("{{{{ text \"{}\" }}}}", read_param!(e, 0)))) as _,
);
plugins
}
/// Set up public directories.
pub(crate) async fn write_assets(config: &Config) -> PathBufD {
vendor_icon!("spotify", VENDOR_SPOTIFY_ICON, config.dirs.icons);
vendor_icon!("last_fm", VENDOR_LAST_FM_ICON, config.dirs.icons);
// ...
let mut plugins = lisp_plugins();
let html_path = PathBufD::current().join(&config.dirs.templates);
write_template!(html_path->"root.html"(crate::assets::ROOT) --config=config --lisp);
write_template!(html_path->"root.html"(crate::assets::ROOT) --config=config --lisp plugins);
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->"misc/error.html"(crate::assets::MISC_ERROR) -d "misc" --config=config --lisp);
write_template!(html_path->"misc/error.html"(crate::assets::MISC_ERROR) -d "misc" --config=config --lisp plugins);
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 --lisp);
write_template!(html_path->"misc/markdown.html"(crate::assets::MISC_MARKDOWN) --config=config --lisp plugins);
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);

View file

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

View file

@ -67,12 +67,12 @@
("class" "card-nest")
(div
("class" "card small flex items-center gap-2 red")
(text "{{ icon \"frown\" }}")
(span (text "{{ text \"general:label.account_banned\" }}")))
(icon (text "frown"))
(str (text "general:label.account_banned")))
(div
("class" "card")
(span (text "{{ text \"general:label.account_banned_body\" }}"))))))
(str (text "general:label.account_banned_body"))))))
; if we aren't banned, just show the page body
(text "{% else %} {% block body %}{% endblock %} {%- endif %}")
@ -150,15 +150,15 @@
("rel" "noopener noreferrer")
("target" "_blank")
("onclick", "document.getElementById('link_filter').close()")
(text "{{ icon \"external-link\" }}")
(span (text "{{ text \"dialog:action.continue\" }}")))
(icon (text "external-link"))
(str (text "dialog:action.continue")))
(button
("class" "secondary")
("type" "button")
("onclick", "document.getElementById('link_filter').close()")
(text "{{ icon \"x\" }}" )
(span (text "{{ text \"dialog:action.cancel\" }}"))))))
(icon (text "x"))
(str (text "dialog:action.cancel"))))))
(dialog
("id" "web_api_prompt")
@ -179,15 +179,15 @@
("class" "primary bold circle")
("onclick", "globalThis.web_api_prompt_submit(document.getElementById('prompt').value); document.getElementById('prompt').value = ''")
("type" "button")
(text "{{ icon \"check\" }}")
(text "{{ text \"dialog:action.okay\" }}"))
(icon (text "check"))
(str (text "dialog:action.okay")))
(button
("class" "bold red camo")
("onclick", "globalThis.web_api_prompt_submit('')")
("type" "button")
(text "{{ icon \"x\" }}")
(text "{{ text \"dialog:action.cancel\" }}")))))))
(icon (text "x"))
(str (text "dialog:action.cancel"))))))))
(dialog
("id" "web_api_prompt_long")
@ -208,15 +208,15 @@
("class" "primary bold circle")
("onclick", "globalThis.web_api_prompt_long_submit(document.getElementById('prompt_long').value); document.getElementById('prompt_long').value = ''")
("type" "button")
(text "{{ icon \"check\" }}")
(text "{{ text \"dialog:action.okay\" }}"))
(icon (text "check"))
(str (text "dialog:action.okay")))
(button
("class" "bold red camo")
("onclick", "globalThis.web_api_prompt_long_submit('')")
("type" "button")
(text "{{ icon \"x\" }}")
(text "{{ text \"dialog:action.cancel\" }}")))))))
(icon (text "x"))
(str (text "dialog:action.cancel"))))))))
(dialog
("id" "web_api_confirm")
@ -236,15 +236,15 @@
("class" "primary bold circle")
("onclick", "globalThis.web_api_confirm_submit(true)")
("type" "button")
(text "{{ icon \"check\" }}")
(text "{{ text \"dialog:action.yes\" }}"))
(icon (text "check"))
(str (text "dialog:action.yes")))
(button
("class" "bold red camo")
("onclick", "globalThis.web_api_confirm_submit(false)")
("type" "button")
(text "{{ icon \"x\" }}")
(text "{{ text \"dialog:action.no\" }}")))))))
(icon (text "x"))
(str (text "dialog:action.no"))))))))
(div
("class" "lightbox hidden")
@ -252,7 +252,7 @@
(button
("class" "lightbox_exit small square quaternary red")
("onclick" "trigger('ui::lightbox_close')")
(text "{{ icon \"x\" }}"))
(icon (text "x")))
(a
("href" "")
@ -274,8 +274,8 @@
("href" "/auth/login")
("class" "button")
("data-turbo", "false")
(text "{{ icon \"plus\" }}")
(span (text "{{ text \"general:action.add_account\" }}")))
(icon (text "plus"))
(span (str (text "general:action.add_account"))))
(div
("class" "flex justify-between")
@ -287,7 +287,7 @@
("class" "quaternary")
("onclick" "document.getElementById('tokens_dialog').close()")
("type" "button")
(text "{{ icon \"check \" }}")
(icon (text "check "))
(span "{{ text \"dialog:action.okay\" }}")))))))
; user scripts