mirror of
https://github.com/typst/typst
synced 2025-05-13 20:46:23 +08:00
Lower and upper on templates
This commit is contained in:
parent
ecd2bca606
commit
efde5cac88
@ -114,8 +114,8 @@ impl Template {
|
||||
if let Some((_, map)) = Arc::get_mut(styled) {
|
||||
if !map.has_scoped() {
|
||||
map.set(key, value);
|
||||
return self;
|
||||
}
|
||||
return self;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -95,6 +95,9 @@ impl TextNode {
|
||||
/// Whether a monospace font should be preferred.
|
||||
#[skip]
|
||||
pub const MONOSPACED: bool = false;
|
||||
/// The case transformation that should be applied to the next.
|
||||
#[skip]
|
||||
pub const CASE: Option<Case> = None;
|
||||
/// Decorative lines.
|
||||
#[skip]
|
||||
#[fold(|a, b| a.into_iter().chain(b).collect())]
|
||||
@ -384,6 +387,25 @@ castable! {
|
||||
.collect(),
|
||||
}
|
||||
|
||||
/// A case transformation on text.
|
||||
#[derive(Debug, Copy, Clone, Eq, PartialEq, Hash)]
|
||||
pub enum Case {
|
||||
/// Everything is uppercased.
|
||||
Upper,
|
||||
/// Everything is lowercased.
|
||||
Lower,
|
||||
}
|
||||
|
||||
impl Case {
|
||||
/// Apply the case to a string of text.
|
||||
pub fn apply(self, text: &str) -> String {
|
||||
match self {
|
||||
Self::Upper => text.to_uppercase(),
|
||||
Self::Lower => text.to_lowercase(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Shape text into [`ShapedText`].
|
||||
pub fn shape<'a>(
|
||||
fonts: &mut FontStore,
|
||||
@ -391,13 +413,18 @@ pub fn shape<'a>(
|
||||
styles: StyleChain<'a>,
|
||||
dir: Dir,
|
||||
) -> ShapedText<'a> {
|
||||
let text = match styles.get(TextNode::CASE) {
|
||||
Some(case) => Cow::Owned(case.apply(text)),
|
||||
None => Cow::Borrowed(text),
|
||||
};
|
||||
|
||||
let mut glyphs = vec![];
|
||||
if !text.is_empty() {
|
||||
shape_segment(
|
||||
fonts,
|
||||
&mut glyphs,
|
||||
0,
|
||||
text,
|
||||
&text,
|
||||
variant(styles),
|
||||
families(styles),
|
||||
None,
|
||||
@ -743,7 +770,7 @@ fn tags(styles: StyleChain) -> Vec<Feature> {
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct ShapedText<'a> {
|
||||
/// The text that was shaped.
|
||||
pub text: &'a str,
|
||||
pub text: Cow<'a, str>,
|
||||
/// The text direction.
|
||||
pub dir: Dir,
|
||||
/// The text's style properties.
|
||||
@ -941,7 +968,7 @@ impl<'a> ShapedText<'a> {
|
||||
if let Some(glyphs) = self.slice_safe_to_break(text_range.clone()) {
|
||||
let (size, baseline) = measure(fonts, glyphs, self.styles);
|
||||
Self {
|
||||
text: &self.text[text_range],
|
||||
text: Cow::Borrowed(&self.text[text_range]),
|
||||
dir: self.dir,
|
||||
styles: self.styles.clone(),
|
||||
size,
|
||||
|
@ -4,6 +4,7 @@ use std::cmp::Ordering;
|
||||
use std::str::FromStr;
|
||||
|
||||
use super::prelude::*;
|
||||
use super::{Case, TextNode};
|
||||
use crate::eval::Array;
|
||||
|
||||
/// Ensure that a condition is fulfilled.
|
||||
@ -253,12 +254,22 @@ pub fn range(_: &mut Context, args: &mut Args) -> TypResult<Value> {
|
||||
|
||||
/// Convert a string to lowercase.
|
||||
pub fn lower(_: &mut Context, args: &mut Args) -> TypResult<Value> {
|
||||
Ok(args.expect::<EcoString>("string")?.to_lowercase().into())
|
||||
case(Case::Lower, args)
|
||||
}
|
||||
|
||||
/// Convert a string to uppercase.
|
||||
pub fn upper(_: &mut Context, args: &mut Args) -> TypResult<Value> {
|
||||
Ok(args.expect::<EcoString>("string")?.to_uppercase().into())
|
||||
case(Case::Upper, args)
|
||||
}
|
||||
|
||||
/// Change the case of a string or template.
|
||||
fn case(case: Case, args: &mut Args) -> TypResult<Value> {
|
||||
let Spanned { v, span } = args.expect("string or template")?;
|
||||
Ok(match v {
|
||||
Value::Str(v) => Value::Str(case.apply(&v).into()),
|
||||
Value::Template(v) => Value::Template(v.styled(TextNode::CASE, Some(case))),
|
||||
v => bail!(span, "expected string or template, found {}", v.type_name()),
|
||||
})
|
||||
}
|
||||
|
||||
/// The length of a string, an array or a dictionary.
|
||||
|
@ -2,7 +2,8 @@
|
||||
|
||||
---
|
||||
// Test the `upper`, `lower`, and number formatting functions.
|
||||
#upper("Abc 8 def")
|
||||
#upper("Abc 8")
|
||||
#upper[def]
|
||||
|
||||
#lower("SCREAMING MUST BE SILENCED in " + roman(1672) + " years")
|
||||
|
||||
@ -14,6 +15,10 @@
|
||||
parbreak()
|
||||
}
|
||||
|
||||
---
|
||||
// Error: 8-9 expected string or template, found integer
|
||||
#upper(1)
|
||||
|
||||
---
|
||||
// Error: 9-11 must be at least zero
|
||||
#symbol(-1)
|
||||
|
Loading…
x
Reference in New Issue
Block a user