mirror of
https://github.com/typst/typst
synced 2025-06-28 16:22:53 +08:00
Allow passing region
to LocalName (#926)
This commit is contained in:
parent
1d42d6674c
commit
a6df909a8d
@ -285,7 +285,7 @@ impl<T: Into<Value>> From<Celled<T>> for Value {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl LocalName for TableElem {
|
impl LocalName for TableElem {
|
||||||
fn local_name(&self, lang: Lang) -> &'static str {
|
fn local_name(&self, lang: Lang, _: Option<Region>) -> &'static str {
|
||||||
match lang {
|
match lang {
|
||||||
Lang::ARABIC => "جدول",
|
Lang::ARABIC => "جدول",
|
||||||
Lang::BOKMÅL => "Tabell",
|
Lang::BOKMÅL => "Tabell",
|
||||||
|
@ -277,7 +277,7 @@ impl Count for EquationElem {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl LocalName for EquationElem {
|
impl LocalName for EquationElem {
|
||||||
fn local_name(&self, lang: Lang) -> &'static str {
|
fn local_name(&self, lang: Lang, _: Option<Region>) -> &'static str {
|
||||||
match lang {
|
match lang {
|
||||||
Lang::ARABIC => "معادلة",
|
Lang::ARABIC => "معادلة",
|
||||||
Lang::BOKMÅL => "Ligning",
|
Lang::BOKMÅL => "Ligning",
|
||||||
@ -305,10 +305,11 @@ impl Refable for EquationElem {
|
|||||||
vt: &mut Vt,
|
vt: &mut Vt,
|
||||||
supplement: Option<Content>,
|
supplement: Option<Content>,
|
||||||
lang: Lang,
|
lang: Lang,
|
||||||
|
region: Option<Region>,
|
||||||
) -> SourceResult<Content> {
|
) -> SourceResult<Content> {
|
||||||
// first we create the supplement of the heading
|
// first we create the supplement of the heading
|
||||||
let mut supplement =
|
let mut supplement =
|
||||||
supplement.unwrap_or_else(|| TextElem::packed(self.local_name(lang)));
|
supplement.unwrap_or_else(|| TextElem::packed(self.local_name(lang, region)));
|
||||||
|
|
||||||
// we append a space if the supplement is not empty
|
// we append a space if the supplement is not empty
|
||||||
if !supplement.is_empty() {
|
if !supplement.is_empty() {
|
||||||
|
@ -152,10 +152,14 @@ impl Show for BibliographyElem {
|
|||||||
|
|
||||||
let mut seq = vec![];
|
let mut seq = vec![];
|
||||||
if let Some(title) = self.title(styles) {
|
if let Some(title) = self.title(styles) {
|
||||||
let title = title.unwrap_or_else(|| {
|
let title =
|
||||||
TextElem::packed(self.local_name(TextElem::lang_in(styles)))
|
title.unwrap_or_else(|| {
|
||||||
|
TextElem::packed(self.local_name(
|
||||||
|
TextElem::lang_in(styles),
|
||||||
|
TextElem::region_in(styles),
|
||||||
|
))
|
||||||
.spanned(self.span())
|
.spanned(self.span())
|
||||||
});
|
});
|
||||||
|
|
||||||
seq.push(HeadingElem::new(title).with_level(NonZeroUsize::ONE).pack());
|
seq.push(HeadingElem::new(title).with_level(NonZeroUsize::ONE).pack());
|
||||||
}
|
}
|
||||||
@ -206,7 +210,7 @@ impl Finalize for BibliographyElem {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl LocalName for BibliographyElem {
|
impl LocalName for BibliographyElem {
|
||||||
fn local_name(&self, lang: Lang) -> &'static str {
|
fn local_name(&self, lang: Lang, _: Option<Region>) -> &'static str {
|
||||||
match lang {
|
match lang {
|
||||||
Lang::ARABIC => "المراجع",
|
Lang::ARABIC => "المراجع",
|
||||||
Lang::BOKMÅL => "Bibliografi",
|
Lang::BOKMÅL => "Bibliografi",
|
||||||
|
@ -193,7 +193,10 @@ impl Synthesize for FigureElem {
|
|||||||
Smart::Auto => match &kind {
|
Smart::Auto => match &kind {
|
||||||
FigureKind::Elem(func) => {
|
FigureKind::Elem(func) => {
|
||||||
let elem = Content::new(*func).with::<dyn LocalName>().map(|c| {
|
let elem = Content::new(*func).with::<dyn LocalName>().map(|c| {
|
||||||
TextElem::packed(c.local_name(TextElem::lang_in(styles)))
|
TextElem::packed(c.local_name(
|
||||||
|
TextElem::lang_in(styles),
|
||||||
|
TextElem::region_in(styles),
|
||||||
|
))
|
||||||
});
|
});
|
||||||
|
|
||||||
if numbering.is_some() {
|
if numbering.is_some() {
|
||||||
@ -273,6 +276,7 @@ impl Refable for FigureElem {
|
|||||||
vt: &mut Vt,
|
vt: &mut Vt,
|
||||||
supplement: Option<Content>,
|
supplement: Option<Content>,
|
||||||
_: Lang,
|
_: Lang,
|
||||||
|
_: Option<Region>,
|
||||||
) -> SourceResult<Content> {
|
) -> SourceResult<Content> {
|
||||||
// If the figure is not numbered, we cannot reference it.
|
// If the figure is not numbered, we cannot reference it.
|
||||||
// Otherwise we build the supplement and numbering scheme.
|
// Otherwise we build the supplement and numbering scheme.
|
||||||
@ -283,7 +287,12 @@ impl Refable for FigureElem {
|
|||||||
Ok(desc)
|
Ok(desc)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn outline(&self, vt: &mut Vt, _: Lang) -> SourceResult<Option<Content>> {
|
fn outline(
|
||||||
|
&self,
|
||||||
|
vt: &mut Vt,
|
||||||
|
_: Lang,
|
||||||
|
_: Option<Region>,
|
||||||
|
) -> SourceResult<Option<Content>> {
|
||||||
// If the figure is not outlined, it is not referenced.
|
// If the figure is not outlined, it is not referenced.
|
||||||
if !self.outlined(StyleChain::default()) {
|
if !self.outlined(StyleChain::default()) {
|
||||||
return Ok(None);
|
return Ok(None);
|
||||||
|
@ -164,13 +164,14 @@ impl Refable for HeadingElem {
|
|||||||
vt: &mut Vt,
|
vt: &mut Vt,
|
||||||
supplement: Option<Content>,
|
supplement: Option<Content>,
|
||||||
lang: Lang,
|
lang: Lang,
|
||||||
|
region: Option<Region>,
|
||||||
) -> SourceResult<Content> {
|
) -> SourceResult<Content> {
|
||||||
// Create the supplement of the heading.
|
// Create the supplement of the heading.
|
||||||
let mut supplement = if let Some(supplement) = supplement {
|
let mut supplement = if let Some(supplement) = supplement {
|
||||||
supplement
|
supplement
|
||||||
} else {
|
} else {
|
||||||
match self.supplement(StyleChain::default()) {
|
match self.supplement(StyleChain::default()) {
|
||||||
Smart::Auto => TextElem::packed(self.local_name(lang)),
|
Smart::Auto => TextElem::packed(self.local_name(lang, region)),
|
||||||
Smart::Custom(None) => Content::empty(),
|
Smart::Custom(None) => Content::empty(),
|
||||||
Smart::Custom(Some(supplement)) => {
|
Smart::Custom(Some(supplement)) => {
|
||||||
supplement.resolve(vt, std::iter::once(Value::from(self.clone())))?
|
supplement.resolve(vt, std::iter::once(Value::from(self.clone())))?
|
||||||
@ -208,7 +209,12 @@ impl Refable for HeadingElem {
|
|||||||
Counter::of(Self::func())
|
Counter::of(Self::func())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn outline(&self, vt: &mut Vt, _: Lang) -> SourceResult<Option<Content>> {
|
fn outline(
|
||||||
|
&self,
|
||||||
|
vt: &mut Vt,
|
||||||
|
_: Lang,
|
||||||
|
_: Option<Region>,
|
||||||
|
) -> SourceResult<Option<Content>> {
|
||||||
// Check whether the heading is outlined.
|
// Check whether the heading is outlined.
|
||||||
if !self.outlined(StyleChain::default()) {
|
if !self.outlined(StyleChain::default()) {
|
||||||
return Ok(None);
|
return Ok(None);
|
||||||
@ -228,7 +234,7 @@ impl Refable for HeadingElem {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl LocalName for HeadingElem {
|
impl LocalName for HeadingElem {
|
||||||
fn local_name(&self, lang: Lang) -> &'static str {
|
fn local_name(&self, lang: Lang, _: Option<Region>) -> &'static str {
|
||||||
match lang {
|
match lang {
|
||||||
Lang::ARABIC => "الفصل",
|
Lang::ARABIC => "الفصل",
|
||||||
Lang::BOKMÅL => "Kapittel",
|
Lang::BOKMÅL => "Kapittel",
|
||||||
|
@ -27,9 +27,10 @@ pub use self::reference::*;
|
|||||||
pub use self::state::*;
|
pub use self::state::*;
|
||||||
|
|
||||||
use typst::doc::Lang;
|
use typst::doc::Lang;
|
||||||
|
use typst::doc::Region;
|
||||||
|
|
||||||
/// The named with which an element is referenced.
|
/// The named with which an element is referenced.
|
||||||
pub trait LocalName {
|
pub trait LocalName {
|
||||||
/// Get the name in the given language.
|
/// Get the name in the given language and (optionally) region.
|
||||||
fn local_name(&self, lang: Lang) -> &'static str;
|
fn local_name(&self, lang: Lang, region: Option<Region>) -> &'static str;
|
||||||
}
|
}
|
||||||
|
@ -1,5 +1,7 @@
|
|||||||
use std::str::FromStr;
|
use std::str::FromStr;
|
||||||
|
|
||||||
|
use typst::util::option_eq;
|
||||||
|
|
||||||
use super::{
|
use super::{
|
||||||
Counter, CounterKey, HeadingElem, LocalName, Numbering, NumberingPattern, Refable,
|
Counter, CounterKey, HeadingElem, LocalName, Numbering, NumberingPattern, Refable,
|
||||||
};
|
};
|
||||||
@ -141,10 +143,14 @@ impl Show for OutlineElem {
|
|||||||
let mut seq = vec![ParbreakElem::new().pack()];
|
let mut seq = vec![ParbreakElem::new().pack()];
|
||||||
// Build the outline title.
|
// Build the outline title.
|
||||||
if let Some(title) = self.title(styles) {
|
if let Some(title) = self.title(styles) {
|
||||||
let title = title.unwrap_or_else(|| {
|
let title =
|
||||||
TextElem::packed(self.local_name(TextElem::lang_in(styles)))
|
title.unwrap_or_else(|| {
|
||||||
|
TextElem::packed(self.local_name(
|
||||||
|
TextElem::lang_in(styles),
|
||||||
|
TextElem::region_in(styles),
|
||||||
|
))
|
||||||
.spanned(self.span())
|
.spanned(self.span())
|
||||||
});
|
});
|
||||||
|
|
||||||
seq.push(HeadingElem::new(title).with_level(NonZeroUsize::ONE).pack());
|
seq.push(HeadingElem::new(title).with_level(NonZeroUsize::ONE).pack());
|
||||||
}
|
}
|
||||||
@ -152,6 +158,7 @@ impl Show for OutlineElem {
|
|||||||
let indent = self.indent(styles);
|
let indent = self.indent(styles);
|
||||||
let depth = self.depth(styles).map_or(usize::MAX, NonZeroUsize::get);
|
let depth = self.depth(styles).map_or(usize::MAX, NonZeroUsize::get);
|
||||||
let lang = TextElem::lang_in(styles);
|
let lang = TextElem::lang_in(styles);
|
||||||
|
let region = TextElem::region_in(styles);
|
||||||
|
|
||||||
let mut ancestors: Vec<&Content> = vec![];
|
let mut ancestors: Vec<&Content> = vec![];
|
||||||
let elems = vt.introspector.query(&self.target(styles));
|
let elems = vt.introspector.query(&self.target(styles));
|
||||||
@ -165,7 +172,7 @@ impl Show for OutlineElem {
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
let Some(outline) = refable.outline(vt, lang)? else {
|
let Some(outline) = refable.outline(vt, lang, region)? else {
|
||||||
continue;
|
continue;
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -255,10 +262,11 @@ impl Finalize for OutlineElem {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl LocalName for OutlineElem {
|
impl LocalName for OutlineElem {
|
||||||
fn local_name(&self, lang: Lang) -> &'static str {
|
fn local_name(&self, lang: Lang, region: Option<Region>) -> &'static str {
|
||||||
match lang {
|
match lang {
|
||||||
Lang::ARABIC => "المحتويات",
|
Lang::ARABIC => "المحتويات",
|
||||||
Lang::BOKMÅL => "Innhold",
|
Lang::BOKMÅL => "Innhold",
|
||||||
|
Lang::CHINESE if option_eq(region, "TW") => "目錄",
|
||||||
Lang::CHINESE => "目录",
|
Lang::CHINESE => "目录",
|
||||||
Lang::CZECH => "Obsah",
|
Lang::CZECH => "Obsah",
|
||||||
Lang::FRENCH => "Table des matières",
|
Lang::FRENCH => "Table des matières",
|
||||||
|
@ -184,10 +184,11 @@ impl Show for RefElem {
|
|||||||
};
|
};
|
||||||
|
|
||||||
let lang = TextElem::lang_in(styles);
|
let lang = TextElem::lang_in(styles);
|
||||||
|
let region = TextElem::region_in(styles);
|
||||||
let reference = elem
|
let reference = elem
|
||||||
.with::<dyn Refable>()
|
.with::<dyn Refable>()
|
||||||
.expect("element should be refable")
|
.expect("element should be refable")
|
||||||
.reference(vt, supplement, lang)?;
|
.reference(vt, supplement, lang, region)?;
|
||||||
|
|
||||||
Ok(reference.linked(Destination::Location(elem.location().unwrap())))
|
Ok(reference.linked(Destination::Location(elem.location().unwrap())))
|
||||||
}
|
}
|
||||||
@ -259,21 +260,27 @@ pub trait Refable {
|
|||||||
///
|
///
|
||||||
/// # Arguments
|
/// # Arguments
|
||||||
/// - `vt` - The virtual typesetter.
|
/// - `vt` - The virtual typesetter.
|
||||||
/// - `styles` - The styles of the reference.
|
|
||||||
/// - `location` - The location where the reference is being created.
|
|
||||||
/// - `supplement` - The supplement of the reference.
|
/// - `supplement` - The supplement of the reference.
|
||||||
|
/// - `lang`: The language of the reference.
|
||||||
|
/// - `region`: The region of the reference.
|
||||||
fn reference(
|
fn reference(
|
||||||
&self,
|
&self,
|
||||||
vt: &mut Vt,
|
vt: &mut Vt,
|
||||||
supplement: Option<Content>,
|
supplement: Option<Content>,
|
||||||
lang: Lang,
|
lang: Lang,
|
||||||
|
region: Option<Region>,
|
||||||
) -> SourceResult<Content>;
|
) -> SourceResult<Content>;
|
||||||
|
|
||||||
/// Tries to build an outline element for this element.
|
/// Tries to build an outline element for this element.
|
||||||
/// If this returns `None`, the outline will not include this element.
|
/// If this returns `None`, the outline will not include this element.
|
||||||
/// By default this just calls [`Refable::reference`].
|
/// By default this just calls [`Refable::reference`].
|
||||||
fn outline(&self, vt: &mut Vt, lang: Lang) -> SourceResult<Option<Content>> {
|
fn outline(
|
||||||
self.reference(vt, None, lang).map(Some)
|
&self,
|
||||||
|
vt: &mut Vt,
|
||||||
|
lang: Lang,
|
||||||
|
region: Option<Region>,
|
||||||
|
) -> SourceResult<Option<Content>> {
|
||||||
|
self.reference(vt, None, lang, region).map(Some)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Returns the level of this element.
|
/// Returns the level of this element.
|
||||||
|
@ -201,7 +201,7 @@ impl Finalize for RawElem {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl LocalName for RawElem {
|
impl LocalName for RawElem {
|
||||||
fn local_name(&self, lang: Lang) -> &'static str {
|
fn local_name(&self, lang: Lang, _: Option<Region>) -> &'static str {
|
||||||
match lang {
|
match lang {
|
||||||
Lang::ARABIC => "قائمة",
|
Lang::ARABIC => "قائمة",
|
||||||
Lang::BOKMÅL => "Utskrift",
|
Lang::BOKMÅL => "Utskrift",
|
||||||
|
@ -122,7 +122,7 @@ impl Layout for ImageElem {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl LocalName for ImageElem {
|
impl LocalName for ImageElem {
|
||||||
fn local_name(&self, lang: Lang) -> &'static str {
|
fn local_name(&self, lang: Lang, _: Option<Region>) -> &'static str {
|
||||||
match lang {
|
match lang {
|
||||||
Lang::ARABIC => "شكل",
|
Lang::ARABIC => "شكل",
|
||||||
Lang::BOKMÅL => "Figur",
|
Lang::BOKMÅL => "Figur",
|
||||||
|
26
src/doc.rs
26
src/doc.rs
@ -591,6 +591,12 @@ impl Region {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl PartialEq<&str> for Region {
|
||||||
|
fn eq(&self, other: &&str) -> bool {
|
||||||
|
self.as_str() == *other
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl FromStr for Region {
|
impl FromStr for Region {
|
||||||
type Err = &'static str;
|
type Err = &'static str;
|
||||||
|
|
||||||
@ -688,3 +694,23 @@ cast_to_value! {
|
|||||||
"y" => Value::Length(v.point.y.into()),
|
"y" => Value::Length(v.point.y.into()),
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[cfg(test)]
|
||||||
|
mod tests {
|
||||||
|
use crate::{doc::Region, util::option_eq};
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_partialeq_str() {
|
||||||
|
let region = Region([b'U', b'S']);
|
||||||
|
assert_eq!(region, "US");
|
||||||
|
assert_ne!(region, "AB");
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_region_option_eq() {
|
||||||
|
let region = Some(Region([b'U', b'S']));
|
||||||
|
|
||||||
|
assert!(option_eq(region, "US"));
|
||||||
|
assert!(!option_eq(region, "AB"));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@ -226,3 +226,13 @@ pub fn pretty_array_like(parts: &[impl AsRef<str>], trailing_comma: bool) -> Str
|
|||||||
buf.push(')');
|
buf.push(')');
|
||||||
buf
|
buf
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Check if the [`Option`]-wrapped L is same to R.
|
||||||
|
///
|
||||||
|
/// This is the stable version of [`Option::contains`].
|
||||||
|
pub fn option_eq<L, R>(left: Option<L>, other: R) -> bool
|
||||||
|
where
|
||||||
|
L: PartialEq<R>,
|
||||||
|
{
|
||||||
|
left.map(|v| v == other).unwrap_or(false)
|
||||||
|
}
|
||||||
|
BIN
tests/ref/text/lang-with-region.png
Normal file
BIN
tests/ref/text/lang-with-region.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 1.4 KiB |
16
tests/typ/text/lang-with-region.typ
Normal file
16
tests/typ/text/lang-with-region.typ
Normal file
@ -0,0 +1,16 @@
|
|||||||
|
// Test if text with region works
|
||||||
|
|
||||||
|
---
|
||||||
|
// without any region
|
||||||
|
#set text(lang: "zh")
|
||||||
|
#outline()
|
||||||
|
|
||||||
|
---
|
||||||
|
// with unknown region configured
|
||||||
|
#set text(lang: "zh", region: "XX")
|
||||||
|
#outline()
|
||||||
|
|
||||||
|
---
|
||||||
|
// with region configured
|
||||||
|
#set text(lang: "zh", region: "TW")
|
||||||
|
#outline()
|
Loading…
x
Reference in New Issue
Block a user