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.
This commit is contained in:
parent
3a99899114
commit
819a108f07
|
@ -46,6 +46,9 @@ This is general information about your book.
|
||||||
`src` directly under the root folder. But this is configurable with the `src`
|
`src` directly under the root folder. But this is configurable with the `src`
|
||||||
key in the configuration file.
|
key in the configuration file.
|
||||||
- **language:** The main language of the book, which is used as a language attribute `<html lang="en">` for example.
|
- **language:** The main language of the book, which is used as a language attribute `<html lang="en">` for example.
|
||||||
|
This is also used to derive the direction of text (RTL, LTR) within the book.
|
||||||
|
- **text_direction**: The direction of text in the book: Left-to-right (LTR) or Right-to-left (RTL). Possible values: `ltr`, `rtl`.
|
||||||
|
When not specified, the correct text direction is derived from the book's `language` attribute.
|
||||||
|
|
||||||
**book.toml**
|
**book.toml**
|
||||||
```toml
|
```toml
|
||||||
|
@ -55,6 +58,7 @@ authors = ["John Doe", "Jane Doe"]
|
||||||
description = "The example book covers examples."
|
description = "The example book covers examples."
|
||||||
src = "my-src" # the source files will be found in `root/my-src` instead of `root/src`
|
src = "my-src" # the source files will be found in `root/my-src` instead of `root/src`
|
||||||
language = "en"
|
language = "en"
|
||||||
|
text-direction = "ltr"
|
||||||
```
|
```
|
||||||
|
|
||||||
### Rust options
|
### Rust options
|
||||||
|
|
220
src/config.rs
220
src/config.rs
|
@ -411,6 +411,9 @@ pub struct BookConfig {
|
||||||
pub multilingual: bool,
|
pub multilingual: bool,
|
||||||
/// The main language of the book.
|
/// The main language of the book.
|
||||||
pub language: Option<String>,
|
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 {
|
impl Default for BookConfig {
|
||||||
|
@ -422,6 +425,44 @@ impl Default for BookConfig {
|
||||||
src: PathBuf::from("src"),
|
src: PathBuf::from("src"),
|
||||||
multilingual: false,
|
multilingual: false,
|
||||||
language: Some(String::from("en")),
|
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,
|
multilingual: true,
|
||||||
src: PathBuf::from("source"),
|
src: PathBuf::from("source"),
|
||||||
language: Some(String::from("ja")),
|
language: Some(String::from("ja")),
|
||||||
|
text_direction: None,
|
||||||
};
|
};
|
||||||
let build_should_be = BuildConfig {
|
let build_should_be = BuildConfig {
|
||||||
build_dir: PathBuf::from("outputs"),
|
build_dir: PathBuf::from("outputs"),
|
||||||
|
@ -1140,6 +1182,184 @@ mod tests {
|
||||||
assert_eq!(&get_404_output_file(&html_config.input_404), "missing.html");
|
assert_eq!(&get_404_output_file(&html_config.input_404), "missing.html");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[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]
|
#[test]
|
||||||
#[should_panic(expected = "Invalid configuration file")]
|
#[should_panic(expected = "Invalid configuration file")]
|
||||||
fn invalid_language_type_error() {
|
fn invalid_language_type_error() {
|
||||||
|
|
Loading…
Reference in New Issue