summaryrefslogtreecommitdiff
path: root/src/library/style.rs
diff options
context:
space:
mode:
authorLaurenz <laurmaedje@gmail.com>2020-12-21 00:40:09 +0100
committerLaurenz <laurmaedje@gmail.com>2020-12-21 00:40:09 +0100
commite59de77f96d43fa675c5c733ccf39ec2c22e949e (patch)
tree84d746c1d1ad863b8c8e2e9fda86ed842634a838 /src/library/style.rs
parent2b660968aa7e1e8efb7c396e17066a1a98c8c10e (diff)
Allow only a few predefined font classes in [font] 🚧
Diffstat (limited to 'src/library/style.rs')
-rw-r--r--src/library/style.rs120
1 files changed, 72 insertions, 48 deletions
diff --git a/src/library/style.rs b/src/library/style.rs
index c641a598..0cc40f94 100644
--- a/src/library/style.rs
+++ b/src/library/style.rs
@@ -10,34 +10,59 @@ use crate::prelude::*;
/// `font`: Configure the font.
///
/// # Positional arguments
-/// - The font size (optional, length or relative to current font size).
-/// - All identifier and string arguments are interpreted as an ordered list of
-/// fallback font families.
+/// - Font size (optional, `linear` relative to current font size).
+/// - Font families ... (optional, variadic, `Family`)
///
-/// An example invocation could look like this:
+/// # Keyword arguments
+/// - `style` (`Style`): The font style.
+/// - `weight` (`Weight`): The font weight.
+/// - `stretch` (`Stretch`): The font stretch.
+/// - `serif` (`Family` or `dict` of type `Family`): The serif family.
+/// - `sans-serif` (`Family` or `dict` of type `Family`): The new sansserif family.
+/// - `monospace` (`Family` or `dict` of type `Family`): The monospace family.
+/// - `emoji` (`Family` or `dict` of type `Family`): The emoji family.
+/// - `math` (`Family` or `dict` of type `Family`): The math family.
+///
+/// # Examples
+/// Set font size and font families.
/// ```typst
-/// [font: 12pt, Arial, "Noto Sans", sans-serif]
+/// [font: 12pt, "Arial", "Noto Sans", sans-serif]
/// ```
///
-/// # Keyword arguments
-/// - `style`
+/// Redefine the default sans-serif family to a single font family.
+/// ```typst
+/// [font: sans-serif="Source Sans Pro"]
+/// ```
+///
+/// Redefine the default emoji family with a fallback.
+/// ```typst
+/// [font: emoji=("Segoe UI Emoji", "Noto Emoji")]
+/// ```
+///
+/// # Enumerations
+/// - `Family`
+/// - `serif`
+/// - `sans-serif`
+/// - `monospace`
+/// - `emoji`
+/// - `math`
+/// - any string
+/// - `Style`
/// - `normal`
/// - `italic`
/// - `oblique`
-///
-/// - `weight`
-/// - `thin` or `hairline` (`100`)
-/// - `extralight` (`200`)
-/// - `light` (`300`)
-/// - `regular` (`400`)
-/// - `medium` (`500`)
-/// - `semibold` (`600`)
-/// - `bold` (`700`)
-/// - `extrabold` (`800`)
-/// - `black` (`900`)
-/// - integer between `100` and `900`
-///
-/// - `stretch`
+/// - `Weight`
+/// - `thin` or `hairline` (100)
+/// - `extralight` (200)
+/// - `light` (300)
+/// - `regular` (400)
+/// - `medium` (500)
+/// - `semibold` (600)
+/// - `bold` (700)
+/// - `extrabold` (800)
+/// - `black` (900)
+/// - any integer between 100 and 900
+/// - `Stretch`
/// - `ultra-condensed`
/// - `extra-condensed`
/// - `condensed`
@@ -47,17 +72,6 @@ use crate::prelude::*;
/// - `expanded`
/// - `extra-expanded`
/// - `ultra-expanded`
-///
-/// - Any other keyword argument whose value is a dictionary of strings defines
-/// a fallback class, for example:
-/// ```typst
-/// [font: serif = ("Source Serif Pro", "Noto Serif")]
-/// ```
-/// This class can be used in the fallback list or other fallback classes as
-/// long as the resulting fallback tree is acyclic.
-/// ```typst
-/// [font: "My Serif", serif]
-/// ```
pub fn font(mut args: Args, ctx: &mut EvalContext) -> Value {
let snapshot = ctx.state.clone();
let body = args.find::<SynTree>();
@@ -71,6 +85,14 @@ pub fn font(mut args: Args, ctx: &mut EvalContext) -> Value {
}
}
+ let mut needs_flattening = false;
+ let list: Vec<_> = args.find_all::<StringLike>().map(|s| s.to_lowercase()).collect();
+
+ if !list.is_empty() {
+ Rc::make_mut(&mut ctx.state.font.families).list = list;
+ needs_flattening = true;
+ }
+
if let Some(style) = args.get::<_, FontStyle>(ctx, "style") {
ctx.state.font.variant.style = style;
}
@@ -83,21 +105,23 @@ pub fn font(mut args: Args, ctx: &mut EvalContext) -> Value {
ctx.state.font.variant.stretch = stretch;
}
- let mut needs_flattening = false;
- let list: Vec<_> = args.find_all::<StringLike>().map(|s| s.to_lowercase()).collect();
- if !list.is_empty() {
- Rc::make_mut(&mut ctx.state.font.families).list = list;
- needs_flattening = true;
- }
+ struct FontList(Vec<String>);
- for (class, dict) in args.find_all_str::<Spanned<ValueDict>>() {
- let fallback = Args(dict)
+ try_from_match!(FontList["font or list of fonts"] @ span:
+ Value::Str(v) => Self(vec![v.to_lowercase()]),
+ Value::Dict(v) => Self(Args(v.span_with(span))
.find_all::<StringLike>()
.map(|s| s.to_lowercase())
- .collect();
-
- Rc::make_mut(&mut ctx.state.font.families).update_class_list(class, fallback);
- needs_flattening = true;
+ .collect()
+ ),
+ );
+
+ for &class in &["serif", "sans-serif", "monospace", "emoji", "math"] {
+ if let Some(list) = args.get::<_, FontList>(ctx, class) {
+ Rc::make_mut(&mut ctx.state.font.families)
+ .update_class_list(class.to_string(), list.0);
+ needs_flattening = true;
+ }
}
if needs_flattening {
@@ -117,10 +141,10 @@ pub fn font(mut args: Args, ctx: &mut EvalContext) -> Value {
/// `rgb`: Create an RGB(A) color.
///
/// # Positional arguments
-/// - The red component (float between 0.0 and 1.0).
-/// - The green component (float between 0.0 and 1.0).
-/// - The blue component (float between 0.0 and 1.0).
-/// - The alpha component (optional, float between 0.0 and 1.0).
+/// - Red component (`float` between 0.0 and 1.0).
+/// - Green component (`float` between 0.0 and 1.0).
+/// - Blue component (`float` between 0.0 and 1.0).
+/// - Alpha component (optional, `float` between 0.0 and 1.0).
pub fn rgb(mut args: Args, ctx: &mut EvalContext) -> Value {
let r = args.need::<_, Spanned<f64>>(ctx, 0, "red component");
let g = args.need::<_, Spanned<f64>>(ctx, 1, "green component");