From a33a05a60ae27ee617404bf9c33cbb88416ae48d Mon Sep 17 00:00:00 2001 From: ElnuDev Date: Sat, 1 Jul 2023 12:36:36 -0700 Subject: [PATCH 01/10] Add furigana tera filter --- Cargo.lock | 5 +++-- Cargo.toml | 1 + src/main.rs | 8 +++++++- src/models/challenge.rs | 2 +- src/utils/furigana.rs | 36 ++++++++++++++++++++++++++++++++++++ src/utils/mod.rs | 5 ++++- 6 files changed, 52 insertions(+), 5 deletions(-) create mode 100644 src/utils/furigana.rs diff --git a/Cargo.lock b/Cargo.lock index 19ff500..5fad90e 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2502,9 +2502,9 @@ dependencies = [ [[package]] name = "regex" -version = "1.8.3" +version = "1.8.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "81ca098a9821bd52d6b24fd8b10bd081f47d39c22778cafaa75a2857a62c6390" +checksum = "d0ab3ca65655bb1e41f2a8c8cd662eb4fb035e67c3f78da1d61dffe89d07300f" dependencies = [ "aho-corasick 1.0.1", "memchr", @@ -3279,6 +3279,7 @@ dependencies = [ "poise", "r2d2", "r2d2_sqlite", + "regex", "reqwest", "rocket 0.5.0-rc.3", "rocket_contrib", diff --git a/Cargo.toml b/Cargo.toml index c068c0f..3349ba5 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -16,6 +16,7 @@ gettext = "0.4.0" poise = "0.5.5" r2d2 = "0.8.10" r2d2_sqlite = "0.22.0" +regex = "1.8.4" reqwest = "0.11.18" rocket = { version = "=0.5.0-rc.3", features = ["secrets", "json"] } rocket_contrib = { version = "0.4.11", features = ["templates"] } diff --git a/src/main.rs b/src/main.rs index aaec564..0d8d1e3 100644 --- a/src/main.rs +++ b/src/main.rs @@ -21,7 +21,7 @@ use routes::*; mod i18n; use i18n::{i18n_filter, load_catalogs}; -use crate::i18n::langs_filter; +use crate::{i18n::langs_filter, utils::furigana_filter}; mod prelude; @@ -106,6 +106,12 @@ async fn rocket() -> Result, rocket::Error> { move |value: &Value, args: &HashMap| { langs_filter(value, args, &langs) }, + ); + engines.tera.register_filter( + "furigana", + move |value: &Value, args: &HashMap| { + furigana_filter(value, args) + }, ) })) .attach(SassFairing::default()) diff --git a/src/models/challenge.rs b/src/models/challenge.rs index 99a9f39..4fcf2a6 100644 --- a/src/models/challenge.rs +++ b/src/models/challenge.rs @@ -4,7 +4,7 @@ use std::str::FromStr; use serde::{Deserialize, Deserializer, Serialize}; use serde_yaml::Value; -use crate::prelude::*; +use crate::{prelude::*}; #[derive(Serialize, Deserialize)] pub struct Challenge { diff --git a/src/utils/furigana.rs b/src/utils/furigana.rs new file mode 100644 index 0000000..1bc4bec --- /dev/null +++ b/src/utils/furigana.rs @@ -0,0 +1,36 @@ +use std::collections::HashMap; + +use regex::Regex; +use rocket_dyn_templates::tera::{self, Value}; + +pub fn furigana_to_html(text: &str) -> String { + // Original regular expression: \[([^\]]*)\]{([^\}]*)} + // https://regexr.com/6dspa + // https://blog.elnu.com/2022/01/furigana-in-markdown-using-regular-expressions/ + // The regex crate users curly braces {} as repetition qualifiers, + // so { needs to be escaped as \{ + // Curly brace literals \{ need to have their backslash escaped as \\{ + // TODO: Modify so only wraps continuous sections of furigana + let re = Regex::new(r"\[([^\]]*)\]\{([^\\}]*)}").unwrap(); + format!("{}", re.replace_all(text, "$1($2)")) +} + +pub fn furigana_filter(value: &Value, _args: &HashMap) -> tera::Result { + Ok(Value::String(furigana_to_html(value.as_str().expect("The furigana input must be a string")))) +} + +#[cfg(test)] +mod tests { + #[test] + fn furigana_to_html() { + use super::furigana_to_html; + assert_eq!( + furigana_to_html("[振]{ふ}り[仮]{が}[名]{な}"), + "\ + ()り\ + ()\ + ()\ + " + ); + } +} \ No newline at end of file diff --git a/src/utils/mod.rs b/src/utils/mod.rs index f8b78ae..5702a3b 100644 --- a/src/utils/mod.rs +++ b/src/utils/mod.rs @@ -5,4 +5,7 @@ mod headers; pub use headers::*; mod challenge; -pub use challenge::*; \ No newline at end of file +pub use challenge::*; + +mod furigana; +pub use furigana::*; \ No newline at end of file From 86f81ccc35ddb47ea59ad0012b3807914021052b Mon Sep 17 00:00:00 2001 From: ElnuDev Date: Sat, 1 Jul 2023 12:40:13 -0700 Subject: [PATCH 02/10] Properly handle songs with only English title --- src/utils/furigana.rs | 3 +++ templates/index.html.tera | 2 +- 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/src/utils/furigana.rs b/src/utils/furigana.rs index 1bc4bec..749ca08 100644 --- a/src/utils/furigana.rs +++ b/src/utils/furigana.rs @@ -16,6 +16,9 @@ pub fn furigana_to_html(text: &str) -> String { } pub fn furigana_filter(value: &Value, _args: &HashMap) -> tera::Result { + if value.is_null() { + return Ok(Value::String("".to_string())); + } Ok(Value::String(furigana_to_html(value.as_str().expect("The furigana input must be a string")))) } diff --git a/templates/index.html.tera b/templates/index.html.tera index 790e832..e620d99 100644 --- a/templates/index.html.tera +++ b/templates/index.html.tera @@ -19,7 +19,7 @@ {% if content.song %}
- {{ content.song.japanese }} + {% if content.song.japanese %}{{ content.song.japanese | furigana | safe }}{% else %}{{ content.song.english }}{% endif %}
{% endif %} {% if user %} From fd6619320ecd3e622041c52e59cb46a97c90dd03 Mon Sep 17 00:00:00 2001 From: ElnuDev Date: Sat, 1 Jul 2023 12:44:23 -0700 Subject: [PATCH 03/10] Add fix for comrak bug not finding frontmatter --- src/models/challenge.rs | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/src/models/challenge.rs b/src/models/challenge.rs index 4fcf2a6..573e3e7 100644 --- a/src/models/challenge.rs +++ b/src/models/challenge.rs @@ -31,8 +31,11 @@ impl Challenge { let arena = Arena::new(); let root = parse_document( &arena, - &fs::read_to_string(format!("content/challenges/{number}.md")) - .expect("Couldn't find challenge file"), + & (fs::read_to_string(format!("content/challenges/{number}.md")) + .expect("Couldn't find challenge file") + // comrak can't find frontmatter if there's only frontmatter and no newline at end + // TODO: Open issue in comrak + + "\n"), &options, ); if let Some(node) = root.children().next() { From 811afd03332abb2b13c166d7e2317c506a1cac4c Mon Sep 17 00:00:00 2001 From: ElnuDev Date: Sat, 1 Jul 2023 12:52:52 -0700 Subject: [PATCH 04/10] Handle challenges with no Japanese content like #59 --- src/models/challenge.rs | 2 +- templates/index.html.tera | 2 ++ 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/src/models/challenge.rs b/src/models/challenge.rs index 573e3e7..b5756dd 100644 --- a/src/models/challenge.rs +++ b/src/models/challenge.rs @@ -8,7 +8,7 @@ use crate::{prelude::*}; #[derive(Serialize, Deserialize)] pub struct Challenge { - pub japanese: Vec>>, + pub japanese: Option>>>, pub english: Option>, pub song: Option, pub youtube: Option, diff --git a/templates/index.html.tera b/templates/index.html.tera index e620d99..2730895 100644 --- a/templates/index.html.tera +++ b/templates/index.html.tera @@ -67,6 +67,7 @@

Welcome to Tegaki Tuesday #{{ challenge }}!

+ {% if content.japanese %}