mirror of
https://github.com/typst/typst
synced 2025-05-14 17:15:28 +08:00
Move lang
functionality into par
This commit is contained in:
parent
370802de13
commit
210c4d9373
@ -458,7 +458,7 @@ impl ParBuilder {
|
|||||||
fn new(style: &Style) -> Self {
|
fn new(style: &Style) -> Self {
|
||||||
Self {
|
Self {
|
||||||
align: style.aligns.block,
|
align: style.aligns.block,
|
||||||
dir: style.dir,
|
dir: style.par.dir,
|
||||||
leading: style.leading(),
|
leading: style.leading(),
|
||||||
children: vec![],
|
children: vec![],
|
||||||
last: Last::None,
|
last: Last::None,
|
||||||
|
@ -125,7 +125,7 @@ impl Walk for EnumNode {
|
|||||||
fn walk_item(ctx: &mut EvalContext, label: EcoString, body: Template) {
|
fn walk_item(ctx: &mut EvalContext, label: EcoString, body: Template) {
|
||||||
ctx.template += Template::from_block(move |style| {
|
ctx.template += Template::from_block(move |style| {
|
||||||
let label = ParNode {
|
let label = ParNode {
|
||||||
dir: style.dir,
|
dir: style.par.dir,
|
||||||
leading: style.leading(),
|
leading: style.leading(),
|
||||||
children: vec![ParChild::Text(
|
children: vec![ParChild::Text(
|
||||||
label.clone(),
|
label.clone(),
|
||||||
|
@ -59,7 +59,6 @@ pub fn new() -> Scope {
|
|||||||
// Text.
|
// Text.
|
||||||
std.def_func("font", font);
|
std.def_func("font", font);
|
||||||
std.def_func("par", par);
|
std.def_func("par", par);
|
||||||
std.def_func("lang", lang);
|
|
||||||
std.def_func("strike", strike);
|
std.def_func("strike", strike);
|
||||||
std.def_func("underline", underline);
|
std.def_func("underline", underline);
|
||||||
std.def_func("overline", overline);
|
std.def_func("overline", overline);
|
||||||
|
@ -15,16 +15,36 @@ pub fn par(ctx: &mut EvalContext, args: &mut Args) -> TypResult<Value> {
|
|||||||
let spacing = args.named("spacing")?;
|
let spacing = args.named("spacing")?;
|
||||||
let leading = args.named("leading")?;
|
let leading = args.named("leading")?;
|
||||||
|
|
||||||
|
let mut dir = args.named::<EcoString>("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::<Spanned<Dir>>("dir")? {
|
||||||
|
if v.axis() == SpecAxis::Horizontal {
|
||||||
|
dir = Some(v)
|
||||||
|
} else {
|
||||||
|
bail!(span, "must be horizontal");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
ctx.template.modify(move |style| {
|
ctx.template.modify(move |style| {
|
||||||
let par = style.par_mut();
|
let par = style.par_mut();
|
||||||
|
|
||||||
if let Some(spacing) = spacing {
|
if let Some(dir) = dir {
|
||||||
par.spacing = spacing;
|
par.dir = dir;
|
||||||
}
|
}
|
||||||
|
|
||||||
if let Some(leading) = leading {
|
if let Some(leading) = leading {
|
||||||
par.leading = leading;
|
par.leading = leading;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if let Some(spacing) = spacing {
|
||||||
|
par.spacing = spacing;
|
||||||
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
ctx.template.parbreak();
|
ctx.template.parbreak();
|
||||||
@ -32,37 +52,6 @@ pub fn par(ctx: &mut EvalContext, args: &mut Args) -> TypResult<Value> {
|
|||||||
Ok(Value::None)
|
Ok(Value::None)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// `lang`: Configure the language.
|
|
||||||
pub fn lang(ctx: &mut EvalContext, args: &mut Args) -> TypResult<Value> {
|
|
||||||
let iso = args.find::<EcoString>();
|
|
||||||
let dir = if let Some(dir) = args.named::<Spanned<Dir>>("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.
|
/// A node that arranges its children into a paragraph.
|
||||||
#[derive(Debug, Hash)]
|
#[derive(Debug, Hash)]
|
||||||
pub struct ParNode {
|
pub struct ParNode {
|
||||||
|
@ -16,8 +16,6 @@ use crate::util::EcoString;
|
|||||||
/// Defines a set of properties a template can be instantiated with.
|
/// Defines a set of properties a template can be instantiated with.
|
||||||
#[derive(Debug, Clone, Eq, PartialEq, Hash)]
|
#[derive(Debug, Clone, Eq, PartialEq, Hash)]
|
||||||
pub struct Style {
|
pub struct Style {
|
||||||
/// The direction for text and other inline objects.
|
|
||||||
pub dir: Dir,
|
|
||||||
/// The alignments of layouts in their parents.
|
/// The alignments of layouts in their parents.
|
||||||
pub aligns: Gen<Align>,
|
pub aligns: Gen<Align>,
|
||||||
/// The page settings.
|
/// The page settings.
|
||||||
@ -58,7 +56,6 @@ impl Style {
|
|||||||
impl Default for Style {
|
impl Default for Style {
|
||||||
fn default() -> Self {
|
fn default() -> Self {
|
||||||
Self {
|
Self {
|
||||||
dir: Dir::LTR,
|
|
||||||
aligns: Gen::splat(Align::Start),
|
aligns: Gen::splat(Align::Start),
|
||||||
page: Rc::new(PageStyle::default()),
|
page: Rc::new(PageStyle::default()),
|
||||||
par: Rc::new(ParStyle::default()),
|
par: Rc::new(ParStyle::default()),
|
||||||
@ -106,17 +103,20 @@ impl Default for PageStyle {
|
|||||||
/// Defines style properties of paragraphs.
|
/// Defines style properties of paragraphs.
|
||||||
#[derive(Debug, Clone, Eq, PartialEq, Hash)]
|
#[derive(Debug, Clone, Eq, PartialEq, Hash)]
|
||||||
pub struct ParStyle {
|
pub struct ParStyle {
|
||||||
/// The spacing between paragraphs (dependent on scaled font size).
|
/// The direction for text and other inline objects.
|
||||||
pub spacing: Linear,
|
pub dir: Dir,
|
||||||
/// The spacing between lines (dependent on scaled font size).
|
/// The spacing between lines (dependent on scaled font size).
|
||||||
pub leading: Linear,
|
pub leading: Linear,
|
||||||
|
/// The spacing between paragraphs (dependent on scaled font size).
|
||||||
|
pub spacing: Linear,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Default for ParStyle {
|
impl Default for ParStyle {
|
||||||
fn default() -> Self {
|
fn default() -> Self {
|
||||||
Self {
|
Self {
|
||||||
spacing: Relative::new(1.2).into(),
|
dir: Dir::LTR,
|
||||||
leading: Relative::new(0.65).into(),
|
leading: Relative::new(0.65).into(),
|
||||||
|
spacing: Relative::new(1.2).into(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -4,35 +4,35 @@
|
|||||||
// Test reordering with different top-level paragraph directions.
|
// Test reordering with different top-level paragraph directions.
|
||||||
#let text = [Text טֶקסט]
|
#let text = [Text טֶקסט]
|
||||||
#font(serif, "Noto Serif Hebrew")
|
#font(serif, "Noto Serif Hebrew")
|
||||||
#lang("he") {text}
|
#par(lang: "he") {text}
|
||||||
#lang("de") {text}
|
#par(lang: "de") {text}
|
||||||
|
|
||||||
---
|
---
|
||||||
// Test that consecutive, embedded LTR runs stay LTR.
|
// Test that consecutive, embedded LTR runs stay LTR.
|
||||||
// Here, we have two runs: "A" and italic "B".
|
// Here, we have two runs: "A" and italic "B".
|
||||||
#let text = [أنت A_B_مطرC]
|
#let text = [أنت A_B_مطرC]
|
||||||
#font(serif, "Noto Sans Arabic")
|
#font(serif, "Noto Sans Arabic")
|
||||||
#lang("ar") {text}
|
#par(lang: "ar") {text}
|
||||||
#lang("de") {text}
|
#par(lang: "de") {text}
|
||||||
|
|
||||||
---
|
---
|
||||||
// Test that consecutive, embedded RTL runs stay RTL.
|
// Test that consecutive, embedded RTL runs stay RTL.
|
||||||
// Here, we have three runs: "גֶ", bold "שֶׁ", and "ם".
|
// Here, we have three runs: "גֶ", bold "שֶׁ", and "ם".
|
||||||
#let text = [Aגֶ*שֶׁ*םB]
|
#let text = [Aגֶ*שֶׁ*םB]
|
||||||
#font(serif, "Noto Serif Hebrew")
|
#font(serif, "Noto Serif Hebrew")
|
||||||
#lang("he") {text}
|
#par(lang: "he") {text}
|
||||||
#lang("de") {text}
|
#par(lang: "de") {text}
|
||||||
|
|
||||||
---
|
---
|
||||||
// Test embedding up to level 4 with isolates.
|
// Test embedding up to level 4 with isolates.
|
||||||
#font(serif, "Noto Serif Hebrew", "Twitter Color Emoji")
|
#font(serif, "Noto Serif Hebrew", "Twitter Color Emoji")
|
||||||
#lang(dir: rtl)
|
#par(dir: rtl)
|
||||||
א\u{2066}A\u{2067}Bב\u{2069}?
|
א\u{2066}A\u{2067}Bב\u{2069}?
|
||||||
|
|
||||||
---
|
---
|
||||||
// Test hard line break (leads to two paragraphs in unicode-bidi).
|
// Test hard line break (leads to two paragraphs in unicode-bidi).
|
||||||
#font("Noto Sans Arabic", serif)
|
#font("Noto Sans Arabic", serif)
|
||||||
#lang("ar")
|
#par(lang: "ar")
|
||||||
Life المطر هو الحياة \
|
Life المطر هو الحياة \
|
||||||
الحياة تمطر is rain.
|
الحياة تمطر is rain.
|
||||||
|
|
||||||
@ -45,12 +45,12 @@ Lריווח #h(1cm) R
|
|||||||
---
|
---
|
||||||
// Test inline object.
|
// Test inline object.
|
||||||
#font("Noto Serif Hebrew", serif)
|
#font("Noto Serif Hebrew", serif)
|
||||||
#lang("he")
|
#par(lang: "he")
|
||||||
קרנפיםRh#image("../../res/rhino.png", height: 11pt)inoחיים
|
קרנפיםRh#image("../../res/rhino.png", height: 11pt)inoחיים
|
||||||
|
|
||||||
---
|
---
|
||||||
// Test the `lang` function.
|
// Test setting a vertical direction.
|
||||||
// Ref: false
|
// Ref: false
|
||||||
|
|
||||||
// Error: 12-15 must be horizontal
|
// Error: 11-14 must be horizontal
|
||||||
#lang(dir: ttb)
|
#par(dir: ttb)
|
||||||
|
@ -41,5 +41,5 @@ A🐈中文B
|
|||||||
// Test reshaping.
|
// Test reshaping.
|
||||||
|
|
||||||
#font("Noto Serif Hebrew")
|
#font("Noto Serif Hebrew")
|
||||||
#lang("he")
|
#par(lang: "he")
|
||||||
ס \ טֶ
|
ס \ טֶ
|
||||||
|
Loading…
x
Reference in New Issue
Block a user