diff --git a/src/library/mod.rs b/src/library/mod.rs index eeda620d2..6a30badf8 100644 --- a/src/library/mod.rs +++ b/src/library/mod.rs @@ -30,6 +30,9 @@ pub fn new() -> Scope { std.def_node::("overline"); std.def_node::("link"); std.def_node::("repeat"); + std.def_fn("lower", text::lower); + std.def_fn("upper", text::upper); + std.def_fn("smallcaps", text::smallcaps); // Structure. std.def_node::("heading"); @@ -67,7 +70,7 @@ pub fn new() -> Scope { // Math. std.def_node::("math"); - // Utility functions. + // Utility. std.def_fn("type", utility::type_); std.def_fn("assert", utility::assert); std.def_fn("int", utility::int); @@ -84,8 +87,6 @@ pub fn new() -> Scope { std.def_fn("repr", utility::repr); std.def_fn("str", utility::str); std.def_fn("regex", utility::regex); - std.def_fn("lower", utility::lower); - std.def_fn("upper", utility::upper); std.def_fn("letter", utility::letter); std.def_fn("roman", utility::roman); std.def_fn("symbol", utility::symbol); diff --git a/src/library/text/mod.rs b/src/library/text/mod.rs index df00d87a9..09c7fa173 100644 --- a/src/library/text/mod.rs +++ b/src/library/text/mod.rs @@ -84,8 +84,6 @@ impl TextNode { /// Whether to apply kerning ("kern"). pub const KERNING: bool = true; - /// Whether small capital glyphs should be used. ("smcp") - pub const SMALLCAPS: bool = false; /// Whether to apply stylistic alternates. ("salt") pub const ALTERNATES: bool = false; /// Which stylistic set to apply. ("ss01" - "ss20") @@ -119,6 +117,9 @@ impl TextNode { /// A case transformation that should be applied to the text. #[property(hidden)] pub const CASE: Option = None; + /// Whether small capital glyphs should be used. ("smcp") + #[property(hidden)] + pub const SMALLCAPS: bool = false; /// An URL the text should link to. #[property(hidden, referenced)] pub const LINK: Option = None; @@ -411,6 +412,26 @@ impl Fold for Vec<(Tag, u32)> { } } +/// Convert text to lowercase. +pub fn lower(_: &mut Context, args: &mut Args) -> TypResult { + case(Case::Lower, args) +} + +/// Convert text to uppercase. +pub fn upper(_: &mut Context, args: &mut Args) -> TypResult { + case(Case::Upper, args) +} + +/// Change the case of text. +fn case(case: Case, args: &mut Args) -> TypResult { + let Spanned { v, span } = args.expect("string or content")?; + Ok(match v { + Value::Str(v) => Value::Str(case.apply(&v).into()), + Value::Content(v) => Value::Content(v.styled(TextNode::CASE, Some(case))), + v => bail!(span, "expected string or content, found {}", v.type_name()), + }) +} + /// A case transformation on text. #[derive(Debug, Copy, Clone, Eq, PartialEq, Hash)] pub enum Case { @@ -430,6 +451,12 @@ impl Case { } } +/// Display text in small capitals. +pub fn smallcaps(_: &mut Context, args: &mut Args) -> TypResult { + let body: Content = args.expect("content")?; + Ok(Value::Content(body.styled(TextNode::SMALLCAPS, true))) +} + /// A toggle that turns on and off alternatingly if folded. #[derive(Debug, Copy, Clone, Eq, PartialEq, Hash)] pub struct Toggle; diff --git a/src/library/utility/string.rs b/src/library/utility/string.rs index 0b309b318..13a6bbd8b 100644 --- a/src/library/utility/string.rs +++ b/src/library/utility/string.rs @@ -2,7 +2,6 @@ use lipsum::lipsum_from_seed; use crate::eval::Regex; use crate::library::prelude::*; -use crate::library::text::{Case, TextNode}; /// The string representation of a value. pub fn repr(_: &mut Context, args: &mut Args) -> TypResult { @@ -20,26 +19,6 @@ pub fn str(_: &mut Context, args: &mut Args) -> TypResult { })) } -/// Convert a string to lowercase. -pub fn lower(_: &mut Context, args: &mut Args) -> TypResult { - case(Case::Lower, args) -} - -/// Convert a string to uppercase. -pub fn upper(_: &mut Context, args: &mut Args) -> TypResult { - case(Case::Upper, args) -} - -/// Change the case of a string or content. -fn case(case: Case, args: &mut Args) -> TypResult { - let Spanned { v, span } = args.expect("string or content")?; - Ok(match v { - Value::Str(v) => Value::Str(case.apply(&v).into()), - Value::Content(v) => Value::Content(v.styled(TextNode::CASE, Some(case))), - v => bail!(span, "expected string or content, found {}", v.type_name()), - }) -} - /// Create blind text. pub fn lorem(_: &mut Context, args: &mut Args) -> TypResult { let words: usize = args.expect("number of words")?; diff --git a/tests/typ/layout/page-style.typ b/tests/typ/layout/page-style.typ index f27551b2b..b4a509efc 100644 --- a/tests/typ/layout/page-style.typ +++ b/tests/typ/layout/page-style.typ @@ -24,5 +24,5 @@ #set page("a4") #set page("a5") #set page("a11", flipped: true, fill: eastern) -#set text("Roboto", white, smallcaps: true) -Typst +#set text("Roboto", white) +#smallcaps[Typst] diff --git a/tests/typ/layout/page.typ b/tests/typ/layout/page.typ index 3157ebf93..918f674b4 100644 --- a/tests/typ/layout/page.typ +++ b/tests/typ/layout/page.typ @@ -23,7 +23,7 @@ --- // Test page fill. #set page(width: 80pt, height: 40pt, fill: eastern) -#text(15pt, "Roboto", fill: white, smallcaps: true)[Typst] +#text(15pt, "Roboto", fill: white, smallcaps[Typst]) #page(width: 40pt, fill: none, margins: (top: 10pt, rest: auto))[Hi] --- diff --git a/tests/typ/style/show-text.typ b/tests/typ/style/show-text.typ index 3bc116f52..f4ecb7e11 100644 --- a/tests/typ/style/show-text.typ +++ b/tests/typ/style/show-text.typ @@ -3,7 +3,7 @@ --- // Test classic example. #set text("Roboto") -#show phrase: "Der Spiegel" as text(smallcaps: true, [#phrase]) +#show phrase: "Der Spiegel" as smallcaps[#phrase] Die Zeitung Der Spiegel existiert. --- diff --git a/tests/typ/text/features.typ b/tests/typ/text/features.typ index 3d1ad6dcd..739230c9f 100644 --- a/tests/typ/text/features.typ +++ b/tests/typ/text/features.typ @@ -8,7 +8,7 @@ --- // Test smallcaps. #set text("Roboto") -#text(smallcaps: true)[Smallcaps] +#smallcaps[Smallcaps] --- // Test alternates and stylistic sets.