Add furigana tera filter
This commit is contained in:
parent
981a78f36e
commit
a33a05a60a
6 changed files with 52 additions and 5 deletions
5
Cargo.lock
generated
5
Cargo.lock
generated
|
@ -2502,9 +2502,9 @@ dependencies = [
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "regex"
|
name = "regex"
|
||||||
version = "1.8.3"
|
version = "1.8.4"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "81ca098a9821bd52d6b24fd8b10bd081f47d39c22778cafaa75a2857a62c6390"
|
checksum = "d0ab3ca65655bb1e41f2a8c8cd662eb4fb035e67c3f78da1d61dffe89d07300f"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"aho-corasick 1.0.1",
|
"aho-corasick 1.0.1",
|
||||||
"memchr",
|
"memchr",
|
||||||
|
@ -3279,6 +3279,7 @@ dependencies = [
|
||||||
"poise",
|
"poise",
|
||||||
"r2d2",
|
"r2d2",
|
||||||
"r2d2_sqlite",
|
"r2d2_sqlite",
|
||||||
|
"regex",
|
||||||
"reqwest",
|
"reqwest",
|
||||||
"rocket 0.5.0-rc.3",
|
"rocket 0.5.0-rc.3",
|
||||||
"rocket_contrib",
|
"rocket_contrib",
|
||||||
|
|
|
@ -16,6 +16,7 @@ gettext = "0.4.0"
|
||||||
poise = "0.5.5"
|
poise = "0.5.5"
|
||||||
r2d2 = "0.8.10"
|
r2d2 = "0.8.10"
|
||||||
r2d2_sqlite = "0.22.0"
|
r2d2_sqlite = "0.22.0"
|
||||||
|
regex = "1.8.4"
|
||||||
reqwest = "0.11.18"
|
reqwest = "0.11.18"
|
||||||
rocket = { version = "=0.5.0-rc.3", features = ["secrets", "json"] }
|
rocket = { version = "=0.5.0-rc.3", features = ["secrets", "json"] }
|
||||||
rocket_contrib = { version = "0.4.11", features = ["templates"] }
|
rocket_contrib = { version = "0.4.11", features = ["templates"] }
|
||||||
|
|
|
@ -21,7 +21,7 @@ use routes::*;
|
||||||
mod i18n;
|
mod i18n;
|
||||||
use i18n::{i18n_filter, load_catalogs};
|
use i18n::{i18n_filter, load_catalogs};
|
||||||
|
|
||||||
use crate::i18n::langs_filter;
|
use crate::{i18n::langs_filter, utils::furigana_filter};
|
||||||
|
|
||||||
mod prelude;
|
mod prelude;
|
||||||
|
|
||||||
|
@ -106,6 +106,12 @@ async fn rocket() -> Result<Rocket<Ignite>, rocket::Error> {
|
||||||
move |value: &Value, args: &HashMap<String, Value>| {
|
move |value: &Value, args: &HashMap<String, Value>| {
|
||||||
langs_filter(value, args, &langs)
|
langs_filter(value, args, &langs)
|
||||||
},
|
},
|
||||||
|
);
|
||||||
|
engines.tera.register_filter(
|
||||||
|
"furigana",
|
||||||
|
move |value: &Value, args: &HashMap<String, Value>| {
|
||||||
|
furigana_filter(value, args)
|
||||||
|
},
|
||||||
)
|
)
|
||||||
}))
|
}))
|
||||||
.attach(SassFairing::default())
|
.attach(SassFairing::default())
|
||||||
|
|
|
@ -4,7 +4,7 @@ use std::str::FromStr;
|
||||||
use serde::{Deserialize, Deserializer, Serialize};
|
use serde::{Deserialize, Deserializer, Serialize};
|
||||||
use serde_yaml::Value;
|
use serde_yaml::Value;
|
||||||
|
|
||||||
use crate::prelude::*;
|
use crate::{prelude::*};
|
||||||
|
|
||||||
#[derive(Serialize, Deserialize)]
|
#[derive(Serialize, Deserialize)]
|
||||||
pub struct Challenge {
|
pub struct Challenge {
|
||||||
|
|
36
src/utils/furigana.rs
Normal file
36
src/utils/furigana.rs
Normal file
|
@ -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 <span lang="ja"> only wraps continuous sections of furigana
|
||||||
|
let re = Regex::new(r"\[([^\]]*)\]\{([^\\}]*)}").unwrap();
|
||||||
|
format!("<span lang=\"ja\">{}</span>", re.replace_all(text, "<ruby>$1<rp>(</rp><rt>$2</rt><rp>)</rp></ruby>"))
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn furigana_filter(value: &Value, _args: &HashMap<String, Value>) -> tera::Result<Value> {
|
||||||
|
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("[振]{ふ}り[仮]{が}[名]{な}"),
|
||||||
|
"<span lang=\"ja\">\
|
||||||
|
<ruby>振<rp>(</rp><rt>ふ</rt><rp>)</rp></ruby>り\
|
||||||
|
<ruby>仮<rp>(</rp><rt>が</rt><rp>)</rp></ruby>\
|
||||||
|
<ruby>名<rp>(</rp><rt>な</rt><rp>)</rp></ruby>\
|
||||||
|
</span>"
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
|
@ -5,4 +5,7 @@ mod headers;
|
||||||
pub use headers::*;
|
pub use headers::*;
|
||||||
|
|
||||||
mod challenge;
|
mod challenge;
|
||||||
pub use challenge::*;
|
pub use challenge::*;
|
||||||
|
|
||||||
|
mod furigana;
|
||||||
|
pub use furigana::*;
|
Loading…
Add table
Reference in a new issue