diff --git a/src/eval/template.rs b/src/eval/template.rs index 795a70493..8fec398de 100644 --- a/src/eval/template.rs +++ b/src/eval/template.rs @@ -458,7 +458,7 @@ impl ParBuilder { fn new(style: &Style) -> Self { Self { align: style.aligns.block, - dir: style.dir, + dir: style.par.dir, leading: style.leading(), children: vec![], last: Last::None, diff --git a/src/eval/walk.rs b/src/eval/walk.rs index d1eb7ac12..7b3fb7a4d 100644 --- a/src/eval/walk.rs +++ b/src/eval/walk.rs @@ -125,7 +125,7 @@ impl Walk for EnumNode { fn walk_item(ctx: &mut EvalContext, label: EcoString, body: Template) { ctx.template += Template::from_block(move |style| { let label = ParNode { - dir: style.dir, + dir: style.par.dir, leading: style.leading(), children: vec![ParChild::Text( label.clone(), diff --git a/src/library/mod.rs b/src/library/mod.rs index d96b370a9..775fb51f3 100644 --- a/src/library/mod.rs +++ b/src/library/mod.rs @@ -59,7 +59,6 @@ pub fn new() -> Scope { // Text. std.def_func("font", font); std.def_func("par", par); - std.def_func("lang", lang); std.def_func("strike", strike); std.def_func("underline", underline); std.def_func("overline", overline); diff --git a/src/library/par.rs b/src/library/par.rs index c781a32de..216b7d410 100644 --- a/src/library/par.rs +++ b/src/library/par.rs @@ -15,16 +15,36 @@ pub fn par(ctx: &mut EvalContext, args: &mut Args) -> TypResult { let spacing = args.named("spacing")?; let leading = args.named("leading")?; + let mut dir = args.named::("lang")?.map(|iso| { + match iso.to_ascii_lowercase().as_str() { + "ar" | "he" | "fa" | "ur" | "ps" | "yi" => Dir::RTL, + "en" | "fr" | "de" => Dir::LTR, + _ => Dir::LTR, + } + }); + + if let Some(Spanned { v, span }) = args.named::>("dir")? { + if v.axis() == SpecAxis::Horizontal { + dir = Some(v) + } else { + bail!(span, "must be horizontal"); + } + } + ctx.template.modify(move |style| { let par = style.par_mut(); - if let Some(spacing) = spacing { - par.spacing = spacing; + if let Some(dir) = dir { + par.dir = dir; } if let Some(leading) = leading { par.leading = leading; } + + if let Some(spacing) = spacing { + par.spacing = spacing; + } }); ctx.template.parbreak(); @@ -32,37 +52,6 @@ pub fn par(ctx: &mut EvalContext, args: &mut Args) -> TypResult { Ok(Value::None) } -/// `lang`: Configure the language. -pub fn lang(ctx: &mut EvalContext, args: &mut Args) -> TypResult { - let iso = args.find::(); - let dir = if let Some(dir) = args.named::>("dir")? { - if dir.v.axis() == SpecAxis::Horizontal { - Some(dir.v) - } else { - bail!(dir.span, "must be horizontal"); - } - } else { - iso.as_deref().map(lang_dir) - }; - - if let Some(dir) = dir { - ctx.template.modify(move |style| style.dir = dir); - } - - ctx.template.parbreak(); - - Ok(Value::None) -} - -/// The default direction for the language identified by the given `iso` code. -fn lang_dir(iso: &str) -> Dir { - match iso.to_ascii_lowercase().as_str() { - "ar" | "he" | "fa" | "ur" | "ps" | "yi" => Dir::RTL, - "en" | "fr" | "de" => Dir::LTR, - _ => Dir::LTR, - } -} - /// A node that arranges its children into a paragraph. #[derive(Debug, Hash)] pub struct ParNode { diff --git a/src/style/mod.rs b/src/style/mod.rs index bb662032b..c2a925683 100644 --- a/src/style/mod.rs +++ b/src/style/mod.rs @@ -16,8 +16,6 @@ use crate::util::EcoString; /// Defines a set of properties a template can be instantiated with. #[derive(Debug, Clone, Eq, PartialEq, Hash)] pub struct Style { - /// The direction for text and other inline objects. - pub dir: Dir, /// The alignments of layouts in their parents. pub aligns: Gen, /// The page settings. @@ -58,7 +56,6 @@ impl Style { impl Default for Style { fn default() -> Self { Self { - dir: Dir::LTR, aligns: Gen::splat(Align::Start), page: Rc::new(PageStyle::default()), par: Rc::new(ParStyle::default()), @@ -106,17 +103,20 @@ impl Default for PageStyle { /// Defines style properties of paragraphs. #[derive(Debug, Clone, Eq, PartialEq, Hash)] pub struct ParStyle { - /// The spacing between paragraphs (dependent on scaled font size). - pub spacing: Linear, + /// The direction for text and other inline objects. + pub dir: Dir, /// The spacing between lines (dependent on scaled font size). pub leading: Linear, + /// The spacing between paragraphs (dependent on scaled font size). + pub spacing: Linear, } impl Default for ParStyle { fn default() -> Self { Self { - spacing: Relative::new(1.2).into(), + dir: Dir::LTR, leading: Relative::new(0.65).into(), + spacing: Relative::new(1.2).into(), } } } diff --git a/tests/typ/text/bidi.typ b/tests/typ/text/bidi.typ index 128e65d42..7d33aeea2 100644 --- a/tests/typ/text/bidi.typ +++ b/tests/typ/text/bidi.typ @@ -4,35 +4,35 @@ // Test reordering with different top-level paragraph directions. #let text = [Text טֶקסט] #font(serif, "Noto Serif Hebrew") -#lang("he") {text} -#lang("de") {text} +#par(lang: "he") {text} +#par(lang: "de") {text} --- // Test that consecutive, embedded LTR runs stay LTR. // Here, we have two runs: "A" and italic "B". #let text = [أنت A_B_مطرC] #font(serif, "Noto Sans Arabic") -#lang("ar") {text} -#lang("de") {text} +#par(lang: "ar") {text} +#par(lang: "de") {text} --- // Test that consecutive, embedded RTL runs stay RTL. // Here, we have three runs: "גֶ", bold "שֶׁ", and "ם". #let text = [Aגֶ*שֶׁ*םB] #font(serif, "Noto Serif Hebrew") -#lang("he") {text} -#lang("de") {text} +#par(lang: "he") {text} +#par(lang: "de") {text} --- // Test embedding up to level 4 with isolates. #font(serif, "Noto Serif Hebrew", "Twitter Color Emoji") -#lang(dir: rtl) +#par(dir: rtl) א\u{2066}A\u{2067}Bב\u{2069}? --- // Test hard line break (leads to two paragraphs in unicode-bidi). #font("Noto Sans Arabic", serif) -#lang("ar") +#par(lang: "ar") Life المطر هو الحياة \ الحياة تمطر is rain. @@ -45,12 +45,12 @@ Lריווח #h(1cm) R --- // Test inline object. #font("Noto Serif Hebrew", serif) -#lang("he") +#par(lang: "he") קרנפיםRh#image("../../res/rhino.png", height: 11pt)inoחיים --- -// Test the `lang` function. +// Test setting a vertical direction. // Ref: false -// Error: 12-15 must be horizontal -#lang(dir: ttb) +// Error: 11-14 must be horizontal +#par(dir: ttb) diff --git a/tests/typ/text/shaping.typ b/tests/typ/text/shaping.typ index aa4e3c98c..1a8a79335 100644 --- a/tests/typ/text/shaping.typ +++ b/tests/typ/text/shaping.typ @@ -41,5 +41,5 @@ A🐈中文B // Test reshaping. #font("Noto Serif Hebrew") -#lang("he") +#par(lang: "he") ס \ טֶ