mirror of
https://github.com/typst/typst
synced 2025-05-13 20:46:23 +08:00
Allow only a few predefined font classes in [font] 🚧
This commit is contained in:
parent
2b660968aa
commit
e59de77f96
@ -150,6 +150,7 @@ fn default_font_families() -> FallbackTree {
|
||||
"serif" => ["source serif pro", "noto serif"],
|
||||
"sans-serif" => ["source sans pro", "noto sans"],
|
||||
"monospace" => ["source code pro", "noto sans mono"],
|
||||
"emoji" => ["segoe ui emoji", "noto emoji"],
|
||||
"math" => ["latin modern math", "serif"],
|
||||
},
|
||||
base: [
|
||||
|
@ -7,7 +7,7 @@ use crate::prelude::*;
|
||||
/// `image`: Insert an image.
|
||||
///
|
||||
/// # Positional arguments
|
||||
/// - The path to the image (string)
|
||||
/// - Path (`string`): The path to the image file.
|
||||
///
|
||||
/// Supports PNG and JPEG files.
|
||||
pub fn image(mut args: Args, ctx: &mut EvalContext) -> Value {
|
||||
|
@ -9,15 +9,26 @@ use crate::prelude::*;
|
||||
/// `align`: Align content along the layouting axes.
|
||||
///
|
||||
/// # Positional arguments
|
||||
/// - At most two of `left`, `right`, `top`, `bottom`, `center`.
|
||||
///
|
||||
/// When `center` is used as a positional argument, it is automatically inferred
|
||||
/// which axis it should apply to depending on further arguments, defaulting
|
||||
/// to the cross axis.
|
||||
/// - first (optional, `Alignment`): An alignment for any of the two axes.
|
||||
/// - second (optional, `Alignment`): An alignment for the other axis.
|
||||
///
|
||||
/// # Keyword arguments
|
||||
/// - `horizontal`: Any of `left`, `right` or `center`.
|
||||
/// - `vertical`: Any of `top`, `bottom` or `center`.
|
||||
/// - `horizontal` (`Alignment`): An alignment for the horizontal axis.
|
||||
/// - `vertical` (`Alignment`): An alignment for the vertical axis.
|
||||
///
|
||||
/// # Enumerations
|
||||
/// - `Alignment`
|
||||
/// - `left`
|
||||
/// - `right`
|
||||
/// - `top`
|
||||
/// - `bottom`
|
||||
/// - `center`
|
||||
///
|
||||
/// # Notes
|
||||
/// Which axis an alignment should apply to (main or cross) is inferred from
|
||||
/// either the argument itself (for anything other than `center`) or from the
|
||||
/// second argument if present, defaulting to the cross axis for a single
|
||||
/// `center` alignment.
|
||||
pub fn align(mut args: Args, ctx: &mut EvalContext) -> Value {
|
||||
let snapshot = ctx.state.clone();
|
||||
let body = args.find::<SynTree>();
|
||||
@ -178,8 +189,8 @@ impl Display for SpecAlign {
|
||||
/// `box`: Layout content into a box.
|
||||
///
|
||||
/// # Keyword arguments
|
||||
/// - `width`: The width of the box (length or relative to parent's width).
|
||||
/// - `height`: The height of the box (length or relative to parent's height).
|
||||
/// - `width` (`linear` relative to parent width): The width of the box.
|
||||
/// - `height` (`linear` relative to parent height): The height of the box.
|
||||
pub fn boxed(mut args: Args, ctx: &mut EvalContext) -> Value {
|
||||
let snapshot = ctx.state.clone();
|
||||
let body = args.find::<SynTree>().unwrap_or_default();
|
||||
@ -219,7 +230,7 @@ pub fn boxed(mut args: Args, ctx: &mut EvalContext) -> Value {
|
||||
/// `h`: Add horizontal spacing.
|
||||
///
|
||||
/// # Positional arguments
|
||||
/// - The spacing (length or relative to font size).
|
||||
/// - Spacing (`linear` relative to font size): The amount of spacing.
|
||||
pub fn h(args: Args, ctx: &mut EvalContext) -> Value {
|
||||
spacing(args, ctx, SpecAxis::Horizontal)
|
||||
}
|
||||
@ -227,7 +238,7 @@ pub fn h(args: Args, ctx: &mut EvalContext) -> Value {
|
||||
/// `v`: Add vertical spacing.
|
||||
///
|
||||
/// # Positional arguments
|
||||
/// - The spacing (length or relative to font size).
|
||||
/// - Spacing (`linear` relative to font size): The amount of spacing.
|
||||
pub fn v(args: Args, ctx: &mut EvalContext) -> Value {
|
||||
spacing(args, ctx, SpecAxis::Vertical)
|
||||
}
|
||||
@ -255,17 +266,20 @@ fn spacing(mut args: Args, ctx: &mut EvalContext, axis: SpecAxis) -> Value {
|
||||
/// `page`: Configure pages.
|
||||
///
|
||||
/// # Positional arguments
|
||||
/// - The name of a paper, e.g. `a4` (optional).
|
||||
/// - Paper name (optional, `Paper`).
|
||||
///
|
||||
/// # Keyword arguments
|
||||
/// - `width`: The width of pages (length).
|
||||
/// - `height`: The height of pages (length).
|
||||
/// - `margins`: The margins for all sides (length or relative to side lengths).
|
||||
/// - `left`: The left margin (length or relative to width).
|
||||
/// - `right`: The right margin (length or relative to width).
|
||||
/// - `top`: The top margin (length or relative to height).
|
||||
/// - `bottom`: The bottom margin (length or relative to height).
|
||||
/// - `flip`: Flips custom or paper-defined width and height (boolean).
|
||||
/// - `width` (`length`): The width of pages.
|
||||
/// - `height` (`length`): The height of pages.
|
||||
/// - `margins` (`linear` relative to sides): The margins for all sides.
|
||||
/// - `left` (`linear` relative to width): The left margin.
|
||||
/// - `right` (`linear` relative to width): The right margin.
|
||||
/// - `top` (`linear` relative to height): The top margin.
|
||||
/// - `bottom` (`linear` relative to height): The bottom margin.
|
||||
/// - `flip` (`bool`): Flips custom or paper-defined width and height.
|
||||
///
|
||||
/// # Enumerations
|
||||
/// - `Paper`: See [here](crate::paper) for a full list.
|
||||
pub fn page(mut args: Args, ctx: &mut EvalContext) -> Value {
|
||||
let snapshot = ctx.state.clone();
|
||||
let body = args.find::<SynTree>();
|
||||
|
@ -12,7 +12,7 @@ use crate::eval::{Scope, ValueFunc};
|
||||
|
||||
macro_rules! std {
|
||||
($($func:expr $(=> $name:expr)?),* $(,)?) => {
|
||||
/// Create a scope with all standard library functions.
|
||||
/// The scope containing all standard library functions.
|
||||
pub fn _std() -> Scope {
|
||||
let mut std = Scope::new();
|
||||
$(
|
||||
|
@ -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.
|
||||
///
|
||||
/// An example invocation could look like this:
|
||||
/// ```typst
|
||||
/// [font: 12pt, Arial, "Noto Sans", sans-serif]
|
||||
/// ```
|
||||
/// - Font size (optional, `linear` relative to current font size).
|
||||
/// - Font families ... (optional, variadic, `Family`)
|
||||
///
|
||||
/// # Keyword arguments
|
||||
/// - `style`
|
||||
/// - `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]
|
||||
/// ```
|
||||
///
|
||||
/// 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();
|
||||
.collect()
|
||||
),
|
||||
);
|
||||
|
||||
Rc::make_mut(&mut ctx.state.font.families).update_class_list(class, fallback);
|
||||
needs_flattening = true;
|
||||
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");
|
||||
|
6
tests/typ/func-font-error.typ
Normal file
6
tests/typ/func-font-error.typ
Normal file
@ -0,0 +1,6 @@
|
||||
// Test error cases of the `font` function.
|
||||
|
||||
[font: something="invalid"]
|
||||
|
||||
// compare-ref: false
|
||||
// error: 3:8-3:27 unexpected argument
|
@ -11,7 +11,7 @@ Emoji: 🏀
|
||||
[font: math][Math: ∫ α + β ➗ 3]
|
||||
|
||||
// Class redefinition.
|
||||
[font: sans-serif=("Noto Emoji",)]
|
||||
[font: sans-serif="Noto Emoji"]
|
||||
[font: sans-serif=("Archivo", sans-serif)]
|
||||
New sans-serif. 🚀
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user