diff options
| author | Laurenz <laurmaedje@gmail.com> | 2022-11-09 18:16:59 +0100 |
|---|---|---|
| committer | Laurenz <laurmaedje@gmail.com> | 2022-11-09 18:20:02 +0100 |
| commit | 010cc2effc2fd0e1c4e52d5c914cb4d74506bc0a (patch) | |
| tree | e50060d271f076b00945e5569e7f8ffef2c28e9f /library/src/structure/heading.rs | |
| parent | 12a59963b08b68cc39dcded4d3d3e6a6631c2732 (diff) | |
New block spacing model
Diffstat (limited to 'library/src/structure/heading.rs')
| -rw-r--r-- | library/src/structure/heading.rs | 102 |
1 files changed, 16 insertions, 86 deletions
diff --git a/library/src/structure/heading.rs b/library/src/structure/heading.rs index fe9b9013..87b522f7 100644 --- a/library/src/structure/heading.rs +++ b/library/src/structure/heading.rs @@ -1,6 +1,6 @@ use typst::font::FontWeight; -use crate::layout::{BlockNode, BlockSpacing}; +use crate::layout::{BlockNode, VNode}; use crate::prelude::*; use crate::text::{TextNode, TextSize}; @@ -16,25 +16,6 @@ pub struct HeadingNode { #[node(Show, Finalize)] impl HeadingNode { - /// Whether the heading appears in the outline. - pub const OUTLINED: bool = true; - /// Whether the heading is numbered. - pub const NUMBERED: bool = true; - - /// The spacing above the heading. - #[property(referenced, shorthand(around))] - pub const ABOVE: Leveled<Option<BlockSpacing>> = Leveled::Mapping(|level| { - let ratio = match level.get() { - 1 => 1.5, - _ => 1.2, - }; - Some(Ratio::new(ratio).into()) - }); - /// The spacing below the heading. - #[property(referenced, shorthand(around))] - pub const BELOW: Leveled<Option<BlockSpacing>> = - Leveled::Value(Some(Ratio::new(0.55).into())); - fn construct(_: &mut Vm, args: &mut Args) -> SourceResult<Content> { Ok(Self { body: args.expect("body")?, @@ -65,76 +46,25 @@ impl Show for HeadingNode { impl Finalize for HeadingNode { fn finalize( &self, - world: Tracked<dyn World>, - styles: StyleChain, - mut realized: Content, + _: Tracked<dyn World>, + _: StyleChain, + realized: Content, ) -> SourceResult<Content> { - macro_rules! resolve { - ($key:expr) => { - styles.get($key).resolve(world, self.level)? - }; - } - - let mut map = StyleMap::new(); - map.set(TextNode::SIZE, { - let size = match self.level.get() { - 1 => 1.4, - 2 => 1.2, - _ => 1.0, - }; - TextSize(Em::new(size).into()) + let size = Em::new(match self.level.get() { + 1 => 1.4, + 2 => 1.2, + _ => 1.0, }); - map.set(TextNode::WEIGHT, FontWeight::BOLD); - realized = realized.styled_with_map(map).spaced( - resolve!(Self::ABOVE).resolve(styles), - resolve!(Self::BELOW).resolve(styles), - ); + let above = Em::new(if self.level.get() == 1 { 1.8 } else { 1.44 }); + let below = Em::new(0.66); - Ok(realized) - } -} - -/// Either the value or a closure mapping to the value. -#[derive(Debug, Clone, PartialEq, Hash)] -pub enum Leveled<T> { - /// A bare value. - Value(T), - /// A simple mapping from a heading level to a value. - Mapping(fn(NonZeroUsize) -> T), - /// A closure mapping from a heading level to a value. - Func(Func, Span), -} - -impl<T: Cast + Clone> Leveled<T> { - /// Resolve the value based on the level. - pub fn resolve( - &self, - world: Tracked<dyn World>, - level: NonZeroUsize, - ) -> SourceResult<T> { - Ok(match self { - Self::Value(value) => value.clone(), - Self::Mapping(mapping) => mapping(level), - Self::Func(func, span) => { - let args = Args::new(*span, [Value::Int(level.get() as i64)]); - func.call_detached(world, args)?.cast().at(*span)? - } - }) - } -} - -impl<T: Cast> Cast<Spanned<Value>> for Leveled<T> { - fn is(value: &Spanned<Value>) -> bool { - matches!(&value.v, Value::Func(_)) || T::is(&value.v) - } + let mut map = StyleMap::new(); + map.set(TextNode::SIZE, TextSize(size.into())); + map.set(TextNode::WEIGHT, FontWeight::BOLD); + map.set(BlockNode::ABOVE, VNode::strong(above.into())); + map.set(BlockNode::BELOW, VNode::strong(below.into())); - fn cast(value: Spanned<Value>) -> StrResult<Self> { - match value.v { - Value::Func(v) => Ok(Self::Func(v, value.span)), - v => T::cast(v) - .map(Self::Value) - .map_err(|msg| with_alternative(msg, "function")), - } + Ok(realized.styled_with_map(map)) } } |
