summaryrefslogtreecommitdiffstats
path: root/src/config.rs
diff options
context:
space:
mode:
authorcN3rd <subs.in.tokyo@gmail.com>2021-09-03 18:31:39 +0300
committerEric Huss <eric@huss.org>2023-09-02 07:49:28 -0700
commit819a108f073c84d835407ea0fe1ff322bd1cf238 (patch)
tree0a8171d499645597c4dfbe77461c14c8c4f475f9 /src/config.rs
parent3a998991141417e4b4d1671c90c8ff9a9398788b (diff)
Add `text_direction` property in general book metadata
Text direction can selected in the config via the `text_direction` attribute in `book.toml`, or be derived from the book's language.
Diffstat (limited to 'src/config.rs')
-rw-r--r--src/config.rs220
1 files changed, 220 insertions, 0 deletions
diff --git a/src/config.rs b/src/config.rs
index 4641d1a2..8a20e4f3 100644
--- a/src/config.rs
+++ b/src/config.rs
@@ -411,6 +411,9 @@ pub struct BookConfig {
pub multilingual: bool,
/// The main language of the book.
pub language: Option<String>,
+ /// The direction of text in the book: Left-to-right (LTR) or Right-to-left (RTL).
+ /// When not specified, the correct text direction is derived from [BookConfig::language].
+ pub text_direction: Option<TextDirection>,
}
impl Default for BookConfig {
@@ -422,6 +425,44 @@ impl Default for BookConfig {
src: PathBuf::from("src"),
multilingual: false,
language: Some(String::from("en")),
+ text_direction: None,
+ }
+ }
+}
+
+impl BookConfig {
+ /// Gets the realized text direction, either from [BookConfig::text_direction]
+ /// or derived from [BookConfig::language], to be used by templating engines.
+ pub fn realized_text_direction(&self) -> TextDirection {
+ if let Some(direction) = self.text_direction {
+ direction
+ } else {
+ TextDirection::from_lang_code(&self.language.clone().unwrap_or_default())
+ }
+ }
+}
+
+/// Text direction to use for HTML output
+#[derive(Debug, Copy, Clone, PartialEq, Serialize, Deserialize)]
+pub enum TextDirection {
+ /// Left to right.
+ #[serde(rename = "ltr")]
+ LeftToRight,
+ /// Right to left
+ #[serde(rename = "rtl")]
+ RightToLeft,
+}
+
+impl TextDirection {
+ /// Gets the text direction from language code
+ pub fn from_lang_code(code: &str) -> Self {
+ match code {
+ // list sourced from here: https://github.com/abarrak/rtl/blob/master/lib/rtl/core.rb#L16
+ "ar" | "ara" | "arc" | "ae" | "ave" | "egy" | "he" | "heb" | "nqo" | "pal" | "phn"
+ | "sam" | "syc" | "syr" | "fa" | "per" | "fas" | "ku" | "kur" | "ur" | "urd" => {
+ TextDirection::RightToLeft
+ }
+ _ => TextDirection::LeftToRight,
}
}
}
@@ -788,6 +829,7 @@ mod tests {
multilingual: true,
src: PathBuf::from("source"),
language: Some(String::from("ja")),
+ text_direction: None,
};
let build_should_be = BuildConfig {
build_dir: PathBuf::from("outputs"),
@@ -1141,6 +1183,184 @@ mod tests {
}
#[test]
+ fn text_direction_ltr() {
+ let src = r#"
+ [book]
+ text-direction = "ltr"
+ "#;
+
+ let got = Config::from_str(src).unwrap();
+ assert_eq!(got.book.text_direction, Some(TextDirection::LeftToRight));
+ }
+
+ #[test]
+ fn text_direction_rtl() {
+ let src = r#"
+ [book]
+ text-direction = "rtl"
+ "#;
+
+ let got = Config::from_str(src).unwrap();
+ assert_eq!(got.book.text_direction, Some(TextDirection::RightToLeft));
+ }
+
+ #[test]
+ fn text_direction_none() {
+ let src = r#"
+ [book]
+ "#;
+
+ let got = Config::from_str(src).unwrap();
+ assert_eq!(got.book.text_direction, None);
+ }
+
+ #[test]
+ fn test_text_direction() {
+ let mut cfg = BookConfig::default();
+
+ // test deriving the text direction from language codes
+ cfg.language = Some("ar".into());
+ assert_eq!(cfg.realized_text_direction(), TextDirection::RightToLeft);
+
+ cfg.language = Some("he".into());
+ assert_eq!(cfg.realized_text_direction(), TextDirection::RightToLeft);
+
+ cfg.language = Some("en".into());
+ assert_eq!(cfg.realized_text_direction(), TextDirection::LeftToRight);
+
+ cfg.language = Some("ja".into());
+ assert_eq!(cfg.realized_text_direction(), TextDirection::LeftToRight);
+
+ // test forced direction
+ cfg.language = Some("ar".into());
+ cfg.text_direction = Some(TextDirection::LeftToRight);
+ assert_eq!(cfg.realized_text_direction(), TextDirection::LeftToRight);
+
+ cfg.language = Some("ar".into());
+ cfg.text_direction = Some(TextDirection::RightToLeft);
+ assert_eq!(cfg.realized_text_direction(), TextDirection::RightToLeft);
+
+ cfg.language = Some("en".into());
+ cfg.text_direction = Some(TextDirection::LeftToRight);
+ assert_eq!(cfg.realized_text_direction(), TextDirection::LeftToRight);
+
+ cfg.language = Some("en".into());
+ cfg.text_direction = Some(TextDirection::RightToLeft);
+ assert_eq!(cfg.realized_text_direction(), TextDirection::RightToLeft);
+ }
+
+ #[test]
+ fn text_drection_from_lang_code() {
+ // test all right-to-left languages
+ assert_eq!(
+ TextDirection::from_lang_code("ar"),
+ TextDirection::RightToLeft
+ );
+ assert_eq!(
+ TextDirection::from_lang_code("ara"),
+ TextDirection::RightToLeft
+ );
+ assert_eq!(
+ TextDirection::from_lang_code("arc"),
+ TextDirection::RightToLeft
+ );
+ assert_eq!(
+ TextDirection::from_lang_code("ae"),
+ TextDirection::RightToLeft
+ );
+ assert_eq!(
+ TextDirection::from_lang_code("ave"),
+ TextDirection::RightToLeft
+ );
+ assert_eq!(
+ TextDirection::from_lang_code("egy"),
+ TextDirection::RightToLeft
+ );
+ assert_eq!(
+ TextDirection::from_lang_code("he"),
+ TextDirection::RightToLeft
+ );
+ assert_eq!(
+ TextDirection::from_lang_code("heb"),
+ TextDirection::RightToLeft
+ );
+ assert_eq!(
+ TextDirection::from_lang_code("nqo"),
+ TextDirection::RightToLeft
+ );
+ assert_eq!(
+ TextDirection::from_lang_code("pal"),
+ TextDirection::RightToLeft
+ );
+ assert_eq!(
+ TextDirection::from_lang_code("phn"),
+ TextDirection::RightToLeft
+ );
+ assert_eq!(
+ TextDirection::from_lang_code("sam"),
+ TextDirection::RightToLeft
+ );
+ assert_eq!(
+ TextDirection::from_lang_code("syc"),
+ TextDirection::RightToLeft
+ );
+ assert_eq!(
+ TextDirection::from_lang_code("syr"),
+ TextDirection::RightToLeft
+ );
+ assert_eq!(
+ TextDirection::from_lang_code("fa"),
+ TextDirection::RightToLeft
+ );
+ assert_eq!(
+ TextDirection::from_lang_code("per"),
+ TextDirection::RightToLeft
+ );
+ assert_eq!(
+ TextDirection::from_lang_code("fas"),
+ TextDirection::RightToLeft
+ );
+ assert_eq!(
+ TextDirection::from_lang_code("ku"),
+ TextDirection::RightToLeft
+ );
+ assert_eq!(
+ TextDirection::from_lang_code("kur"),
+ TextDirection::RightToLeft
+ );
+ assert_eq!(
+ TextDirection::from_lang_code("ur"),
+ TextDirection::RightToLeft
+ );
+ assert_eq!(
+ TextDirection::from_lang_code("urd"),
+ TextDirection::RightToLeft
+ );
+
+ // test some left-to-right languages
+ assert_eq!(
+ TextDirection::from_lang_code("de"),
+ TextDirection::LeftToRight
+ );
+ assert_eq!(
+ TextDirection::from_lang_code("en"),
+ TextDirection::LeftToRight
+ );
+ assert_eq!(
+ TextDirection::from_lang_code("es"),
+ TextDirection::LeftToRight
+ );
+ assert_eq!(
+ TextDirection::from_lang_code("ja"),
+ TextDirection::LeftToRight
+ );
+ assert_eq!(
+ TextDirection::from_lang_code("sv"),
+ TextDirection::LeftToRight
+ );
+ }
+
+ #[test]
#[should_panic(expected = "Invalid configuration file")]
fn invalid_language_type_error() {
let src = r#"