mirror of
https://github.com/typst/typst
synced 2025-05-14 17:15:28 +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 let Some((_, map)) = Arc::get_mut(styled) {
|
||||||
if !map.has_scoped() {
|
if !map.has_scoped() {
|
||||||
map.set(key, value);
|
map.set(key, value);
|
||||||
|
return self;
|
||||||
}
|
}
|
||||||
return self;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -95,6 +95,9 @@ impl TextNode {
|
|||||||
/// Whether a monospace font should be preferred.
|
/// Whether a monospace font should be preferred.
|
||||||
#[skip]
|
#[skip]
|
||||||
pub const MONOSPACED: bool = false;
|
pub const MONOSPACED: bool = false;
|
||||||
|
/// The case transformation that should be applied to the next.
|
||||||
|
#[skip]
|
||||||
|
pub const CASE: Option<Case> = None;
|
||||||
/// Decorative lines.
|
/// Decorative lines.
|
||||||
#[skip]
|
#[skip]
|
||||||
#[fold(|a, b| a.into_iter().chain(b).collect())]
|
#[fold(|a, b| a.into_iter().chain(b).collect())]
|
||||||
@ -384,6 +387,25 @@ castable! {
|
|||||||
.collect(),
|
.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`].
|
/// Shape text into [`ShapedText`].
|
||||||
pub fn shape<'a>(
|
pub fn shape<'a>(
|
||||||
fonts: &mut FontStore,
|
fonts: &mut FontStore,
|
||||||
@ -391,13 +413,18 @@ pub fn shape<'a>(
|
|||||||
styles: StyleChain<'a>,
|
styles: StyleChain<'a>,
|
||||||
dir: Dir,
|
dir: Dir,
|
||||||
) -> ShapedText<'a> {
|
) -> ShapedText<'a> {
|
||||||
|
let text = match styles.get(TextNode::CASE) {
|
||||||
|
Some(case) => Cow::Owned(case.apply(text)),
|
||||||
|
None => Cow::Borrowed(text),
|
||||||
|
};
|
||||||
|
|
||||||
let mut glyphs = vec![];
|
let mut glyphs = vec![];
|
||||||
if !text.is_empty() {
|
if !text.is_empty() {
|
||||||
shape_segment(
|
shape_segment(
|
||||||
fonts,
|
fonts,
|
||||||
&mut glyphs,
|
&mut glyphs,
|
||||||
0,
|
0,
|
||||||
text,
|
&text,
|
||||||
variant(styles),
|
variant(styles),
|
||||||
families(styles),
|
families(styles),
|
||||||
None,
|
None,
|
||||||
@ -743,7 +770,7 @@ fn tags(styles: StyleChain) -> Vec<Feature> {
|
|||||||
#[derive(Debug, Clone)]
|
#[derive(Debug, Clone)]
|
||||||
pub struct ShapedText<'a> {
|
pub struct ShapedText<'a> {
|
||||||
/// The text that was shaped.
|
/// The text that was shaped.
|
||||||
pub text: &'a str,
|
pub text: Cow<'a, str>,
|
||||||
/// The text direction.
|
/// The text direction.
|
||||||
pub dir: Dir,
|
pub dir: Dir,
|
||||||
/// The text's style properties.
|
/// 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()) {
|
if let Some(glyphs) = self.slice_safe_to_break(text_range.clone()) {
|
||||||
let (size, baseline) = measure(fonts, glyphs, self.styles);
|
let (size, baseline) = measure(fonts, glyphs, self.styles);
|
||||||
Self {
|
Self {
|
||||||
text: &self.text[text_range],
|
text: Cow::Borrowed(&self.text[text_range]),
|
||||||
dir: self.dir,
|
dir: self.dir,
|
||||||
styles: self.styles.clone(),
|
styles: self.styles.clone(),
|
||||||
size,
|
size,
|
||||||
|
@ -4,6 +4,7 @@ use std::cmp::Ordering;
|
|||||||
use std::str::FromStr;
|
use std::str::FromStr;
|
||||||
|
|
||||||
use super::prelude::*;
|
use super::prelude::*;
|
||||||
|
use super::{Case, TextNode};
|
||||||
use crate::eval::Array;
|
use crate::eval::Array;
|
||||||
|
|
||||||
/// Ensure that a condition is fulfilled.
|
/// 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.
|
/// Convert a string to lowercase.
|
||||||
pub fn lower(_: &mut Context, args: &mut Args) -> TypResult<Value> {
|
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.
|
/// Convert a string to uppercase.
|
||||||
pub fn upper(_: &mut Context, args: &mut Args) -> TypResult<Value> {
|
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.
|
/// The length of a string, an array or a dictionary.
|
||||||
|
@ -2,7 +2,8 @@
|
|||||||
|
|
||||||
---
|
---
|
||||||
// Test the `upper`, `lower`, and number formatting functions.
|
// 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")
|
#lower("SCREAMING MUST BE SILENCED in " + roman(1672) + " years")
|
||||||
|
|
||||||
@ -14,6 +15,10 @@
|
|||||||
parbreak()
|
parbreak()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
---
|
||||||
|
// Error: 8-9 expected string or template, found integer
|
||||||
|
#upper(1)
|
||||||
|
|
||||||
---
|
---
|
||||||
// Error: 9-11 must be at least zero
|
// Error: 9-11 must be at least zero
|
||||||
#symbol(-1)
|
#symbol(-1)
|
||||||
|
Loading…
x
Reference in New Issue
Block a user