typst_library/model/
title.rs1use crate::diag::{Hint, HintedStrResult};
2use crate::foundations::{Content, Packed, ShowSet, Smart, StyleChain, Styles, elem};
3use crate::introspection::{Locatable, Tagged};
4use crate::layout::{BlockElem, Em};
5use crate::model::DocumentElem;
6use crate::text::{FontWeight, TextElem, TextSize};
7
8#[elem(Locatable, Tagged, ShowSet)]
33pub struct TitleElem {
34    #[positional]
47    pub body: Smart<Content>,
48}
49
50impl TitleElem {
51    pub fn resolve_body(&self, styles: StyleChain) -> HintedStrResult<Content> {
52        match self.body.get_cloned(styles) {
53            Smart::Auto => styles
54                .get_cloned(DocumentElem::title)
55                .ok_or("document title was not set")
56                .hint("set the title with `set document(title: [...])`")
57                .hint("or provide an explicit body with `title[..]`"),
58            Smart::Custom(body) => Ok(body),
59        }
60    }
61}
62
63impl ShowSet for Packed<TitleElem> {
64    fn show_set(&self, _styles: StyleChain) -> Styles {
65        const SIZE: Em = Em::new(1.7);
66        const ABOVE: Em = Em::new(1.125);
67        const BELOW: Em = Em::new(0.75);
68
69        let mut out = Styles::new();
70        out.set(TextElem::size, TextSize(SIZE.into()));
71        out.set(TextElem::weight, FontWeight::BOLD);
72        out.set(BlockElem::above, Smart::Custom(ABOVE.into()));
73        out.set(BlockElem::below, Smart::Custom(BELOW.into()));
74        out.set(BlockElem::sticky, true);
75        out
76    }
77}