diff --git a/crates/typst-library/src/text/mod.rs b/crates/typst-library/src/text/mod.rs index 3aac15ba5..462d16060 100644 --- a/crates/typst-library/src/text/mod.rs +++ b/crates/typst-library/src/text/mod.rs @@ -42,7 +42,7 @@ use ttf_parser::Tag; use typst_syntax::Spanned; use typst_utils::singleton; -use crate::diag::{bail, warning, HintedStrResult, SourceResult}; +use crate::diag::{bail, warning, HintedStrResult, SourceResult, StrResult}; use crate::engine::Engine; use crate::foundations::{ cast, dict, elem, Args, Array, Cast, Construct, Content, Dict, Fold, IntoValue, @@ -891,9 +891,21 @@ cast! { } /// Font family fallback list. +/// +/// Must contain at least one font. #[derive(Debug, Default, Clone, PartialEq, Hash)] pub struct FontList(pub Vec); +impl FontList { + pub fn new(fonts: Vec) -> StrResult { + if fonts.is_empty() { + bail!("font fallback list must not be empty") + } else { + Ok(Self(fonts)) + } + } +} + impl<'a> IntoIterator for &'a FontList { type IntoIter = std::slice::Iter<'a, FontFamily>; type Item = &'a FontFamily; @@ -911,7 +923,7 @@ cast! { self.0.into_value() }, family: FontFamily => Self(vec![family]), - values: Array => Self(values.into_iter().map(|v| v.cast()).collect::>()?), + values: Array => Self::new(values.into_iter().map(|v| v.cast()).collect::>()?)?, } /// Resolve a prioritized iterator over the font families. diff --git a/tests/suite/text/font.typ b/tests/suite/text/font.typ index 60a1cd94d..6e21dfd23 100644 --- a/tests/suite/text/font.typ +++ b/tests/suite/text/font.typ @@ -149,3 +149,7 @@ The number 123. #set text(-1pt) a + +--- empty-text-font-array --- +// Error: 17-19 font fallback list must not be empty +#set text(font: ())