summaryrefslogtreecommitdiff
path: root/src/library
diff options
context:
space:
mode:
authorLaurenz <laurmaedje@gmail.com>2022-02-18 15:02:02 +0100
committerLaurenz <laurmaedje@gmail.com>2022-02-18 16:57:53 +0100
commite01970b20a058ab1b4ebea916f229c9b706c84e4 (patch)
tree5c5efc75abd6e607bd45a0602603231edf520503 /src/library
parent05ec0f993b4a1b8481e494ee16285d23f000872f (diff)
Basic show rules
Diffstat (limited to 'src/library')
-rw-r--r--src/library/deco.rs22
-rw-r--r--src/library/heading.rs20
-rw-r--r--src/library/link.rs36
-rw-r--r--src/library/list.rs35
-rw-r--r--src/library/math.rs19
-rw-r--r--src/library/raw.rs14
-rw-r--r--src/library/table.rs16
-rw-r--r--src/library/text.rs12
8 files changed, 117 insertions, 57 deletions
diff --git a/src/library/deco.rs b/src/library/deco.rs
index 79026288..aac79d05 100644
--- a/src/library/deco.rs
+++ b/src/library/deco.rs
@@ -32,15 +32,19 @@ impl<const L: DecoLine> DecoNode<L> {
}
impl<const L: DecoLine> Show for DecoNode<L> {
- fn show(&self, _: &mut Vm, styles: StyleChain) -> TypResult<Template> {
- Ok(self.0.clone().styled(TextNode::LINES, vec![Decoration {
- line: L,
- stroke: styles.get(Self::STROKE),
- thickness: styles.get(Self::THICKNESS),
- offset: styles.get(Self::OFFSET),
- extent: styles.get(Self::EXTENT),
- evade: styles.get(Self::EVADE),
- }]))
+ fn show(&self, vm: &mut Vm, styles: StyleChain) -> TypResult<Template> {
+ Ok(styles
+ .show(self, vm, [Value::Template(self.0.clone())])?
+ .unwrap_or_else(|| {
+ self.0.clone().styled(TextNode::LINES, vec![Decoration {
+ line: L,
+ stroke: styles.get(Self::STROKE),
+ thickness: styles.get(Self::THICKNESS),
+ offset: styles.get(Self::OFFSET),
+ extent: styles.get(Self::EXTENT),
+ evade: styles.get(Self::EVADE),
+ }])
+ }))
}
}
diff --git a/src/library/heading.rs b/src/library/heading.rs
index 1b8fcef9..49975655 100644
--- a/src/library/heading.rs
+++ b/src/library/heading.rs
@@ -34,6 +34,8 @@ impl HeadingNode {
pub const ABOVE: Leveled<Length> = Leveled::Value(Length::zero());
/// The extra padding below the heading.
pub const BELOW: Leveled<Length> = Leveled::Value(Length::zero());
+ /// Whether the heading is block-level.
+ pub const BLOCK: Leveled<bool> = Leveled::Value(true);
fn construct(_: &mut Vm, args: &mut Args) -> TypResult<Template> {
Ok(Template::show(Self {
@@ -51,6 +53,14 @@ impl Show for HeadingNode {
};
}
+ // Resolve the user recipe.
+ let mut body = styles
+ .show(self, vm, [
+ Value::Int(self.level as i64),
+ Value::Template(self.body.clone()),
+ ])?
+ .unwrap_or_else(|| self.body.clone());
+
let mut map = StyleMap::new();
map.set(TextNode::SIZE, resolve!(Self::SIZE));
@@ -76,7 +86,6 @@ impl Show for HeadingNode {
}
let mut seq = vec![];
- let mut body = self.body.clone();
if resolve!(Self::UNDERLINE) {
body = body.underlined();
}
@@ -93,9 +102,12 @@ impl Show for HeadingNode {
seq.push(Template::Vertical(below.into()));
}
- Ok(Template::block(
- Template::sequence(seq).styled_with_map(map),
- ))
+ let mut template = Template::sequence(seq).styled_with_map(map);
+ if resolve!(Self::BLOCK) {
+ template = Template::block(template);
+ }
+
+ Ok(template)
}
}
diff --git a/src/library/link.rs b/src/library/link.rs
index 95fff089..41209549 100644
--- a/src/library/link.rs
+++ b/src/library/link.rs
@@ -10,7 +10,7 @@ pub struct LinkNode {
/// The url the link points to.
pub url: EcoString,
/// How the link is represented.
- pub body: Template,
+ pub body: Option<Template>,
}
#[class]
@@ -22,22 +22,31 @@ impl LinkNode {
pub const UNDERLINE: bool = true;
fn construct(_: &mut Vm, args: &mut Args) -> TypResult<Template> {
- let url = args.expect::<EcoString>("url")?;
- let body = args.find()?.unwrap_or_else(|| {
- let mut text = url.as_str();
- for prefix in ["mailto:", "tel:"] {
- text = text.trim_start_matches(prefix);
- }
- let shorter = text.len() < url.len();
- Template::Text(if shorter { text.into() } else { url.clone() })
- });
-
- Ok(Template::show(Self { url, body }))
+ Ok(Template::show(Self {
+ url: args.expect::<EcoString>("url")?,
+ body: args.find()?,
+ }))
}
}
impl Show for LinkNode {
- fn show(&self, _: &mut Vm, styles: StyleChain) -> TypResult<Template> {
+ fn show(&self, vm: &mut Vm, styles: StyleChain) -> TypResult<Template> {
+ let mut body = styles
+ .show(self, vm, [Value::Str(self.url.clone()), match &self.body {
+ Some(body) => Value::Template(body.clone()),
+ None => Value::None,
+ }])?
+ .or_else(|| self.body.clone())
+ .unwrap_or_else(|| {
+ let url = &self.url;
+ let mut text = url.as_str();
+ for prefix in ["mailto:", "tel:"] {
+ text = text.trim_start_matches(prefix);
+ }
+ let shorter = text.len() < url.len();
+ Template::Text(if shorter { text.into() } else { url.clone() })
+ });
+
let mut map = StyleMap::new();
map.set(TextNode::LINK, Some(self.url.clone()));
@@ -45,7 +54,6 @@ impl Show for LinkNode {
map.set(TextNode::FILL, fill);
}
- let mut body = self.body.clone();
if styles.get(Self::UNDERLINE) {
body = body.underlined();
}
diff --git a/src/library/list.rs b/src/library/list.rs
index 13f21a04..37dda843 100644
--- a/src/library/list.rs
+++ b/src/library/list.rs
@@ -8,13 +8,13 @@ use crate::parse::Scanner;
/// An unordered or ordered list.
#[derive(Debug, Hash)]
pub struct ListNode<const L: ListKind> {
- /// The individual bulleted or numbered items.
- pub items: Vec<ListItem>,
+ /// Where the list starts.
+ pub start: usize,
/// If true, there is paragraph spacing between the items, if false
/// there is list spacing between the items.
pub wide: bool,
- /// Where the list starts.
- pub start: usize,
+ /// The individual bulleted or numbered items.
+ pub items: Vec<ListItem>,
}
/// An item in a list.
@@ -23,7 +23,7 @@ pub struct ListItem {
/// The number of the item.
pub number: Option<usize>,
/// The node that produces the item's body.
- pub body: LayoutNode,
+ pub body: Box<Template>,
}
#[class]
@@ -39,19 +39,27 @@ impl<const L: ListKind> ListNode<L> {
fn construct(_: &mut Vm, args: &mut Args) -> TypResult<Template> {
Ok(Template::show(Self {
+ start: args.named("start")?.unwrap_or(0),
+ wide: args.named("wide")?.unwrap_or(false),
items: args
.all()?
.into_iter()
- .map(|body| ListItem { number: None, body })
+ .map(|body| ListItem { number: None, body: Box::new(body) })
.collect(),
- wide: args.named("wide")?.unwrap_or(false),
- start: args.named("start")?.unwrap_or(0),
}))
}
}
impl<const L: ListKind> Show for ListNode<L> {
fn show(&self, vm: &mut Vm, styles: StyleChain) -> TypResult<Template> {
+ if let Some(template) = styles.show(
+ self,
+ vm,
+ self.items.iter().map(|item| Value::Template((*item.body).clone())),
+ )? {
+ return Ok(template);
+ }
+
let mut children = vec![];
let mut number = self.start;
@@ -66,7 +74,7 @@ impl<const L: ListKind> Show for ListNode<L> {
children.push(LayoutNode::default());
children.push(label.resolve(vm, L, number)?.pack());
children.push(LayoutNode::default());
- children.push(item.body.clone());
+ children.push((*item.body).clone().pack());
number += 1;
}
@@ -119,8 +127,6 @@ pub enum Label {
Pattern(EcoString, Numbering, bool, EcoString),
/// A bare template.
Template(Template),
- /// A simple mapping from an item number to a template.
- Mapping(fn(usize) -> Template),
/// A closure mapping from an item number to a value.
Func(Func, Span),
}
@@ -144,10 +150,9 @@ impl Label {
Template::Text(format_eco!("{}{}{}", prefix, mid, suffix))
}
Self::Template(template) => template.clone(),
- Self::Mapping(mapping) => mapping(number),
- &Self::Func(ref func, span) => {
- let args = Args::from_values(span, [Value::Int(number as i64)]);
- func.call(vm, args)?.cast().at(span)?
+ Self::Func(func, span) => {
+ let args = Args::from_values(*span, [Value::Int(number as i64)]);
+ func.call(vm, args)?.cast().at(*span)?
}
})
}
diff --git a/src/library/math.rs b/src/library/math.rs
index d3c8b5e5..40a1990e 100644
--- a/src/library/math.rs
+++ b/src/library/math.rs
@@ -22,11 +22,18 @@ impl MathNode {
}
impl Show for MathNode {
- fn show(&self, _: &mut Vm, _: StyleChain) -> TypResult<Template> {
- let mut template = Template::Text(self.formula.trim().into());
- if self.display {
- template = Template::Block(template.pack());
- }
- Ok(template.monospaced())
+ fn show(&self, vm: &mut Vm, styles: StyleChain) -> TypResult<Template> {
+ Ok(styles
+ .show(self, vm, [
+ Value::Str(self.formula.clone()),
+ Value::Bool(self.display),
+ ])?
+ .unwrap_or_else(|| {
+ let mut template = Template::Text(self.formula.trim().into());
+ if self.display {
+ template = Template::Block(template.pack());
+ }
+ template.monospaced()
+ }))
}
}
diff --git a/src/library/raw.rs b/src/library/raw.rs
index da926679..bb4e2c96 100644
--- a/src/library/raw.rs
+++ b/src/library/raw.rs
@@ -40,8 +40,20 @@ impl RawNode {
}
impl Show for RawNode {
- fn show(&self, _: &mut Vm, styles: StyleChain) -> TypResult<Template> {
+ fn show(&self, vm: &mut Vm, styles: StyleChain) -> TypResult<Template> {
let lang = styles.get_ref(Self::LANG).as_ref();
+
+ if let Some(template) = styles.show(self, vm, [
+ Value::Str(self.text.clone()),
+ match lang {
+ Some(lang) => Value::Str(lang.clone()),
+ None => Value::None,
+ },
+ Value::Bool(self.block),
+ ])? {
+ return Ok(template);
+ }
+
let foreground = THEME
.settings
.foreground
diff --git a/src/library/table.rs b/src/library/table.rs
index 8c088c09..f4de0f55 100644
--- a/src/library/table.rs
+++ b/src/library/table.rs
@@ -11,7 +11,7 @@ pub struct TableNode {
/// Defines sizing of gutter rows and columns between content.
pub gutter: Spec<Vec<TrackSizing>>,
/// The nodes to be arranged in the table.
- pub children: Vec<LayoutNode>,
+ pub children: Vec<Template>,
}
#[class]
@@ -55,7 +55,15 @@ impl TableNode {
}
impl Show for TableNode {
- fn show(&self, _: &mut Vm, styles: StyleChain) -> TypResult<Template> {
+ fn show(&self, vm: &mut Vm, styles: StyleChain) -> TypResult<Template> {
+ if let Some(template) = styles.show(
+ self,
+ vm,
+ self.children.iter().map(|child| Value::Template(child.clone())),
+ )? {
+ return Ok(template);
+ }
+
let primary = styles.get(Self::PRIMARY);
let secondary = styles.get(Self::SECONDARY);
let thickness = styles.get(Self::THICKNESS);
@@ -68,8 +76,8 @@ impl Show for TableNode {
.iter()
.cloned()
.enumerate()
- .map(|(i, mut child)| {
- child = child.padded(Sides::splat(padding));
+ .map(|(i, child)| {
+ let mut child = child.pack().padded(Sides::splat(padding));
if let Some(stroke) = stroke {
child = child.stroked(stroke);
diff --git a/src/library/text.rs b/src/library/text.rs
index 721a8eac..a67fbcf5 100644
--- a/src/library/text.rs
+++ b/src/library/text.rs
@@ -123,8 +123,10 @@ impl StrongNode {
}
impl Show for StrongNode {
- fn show(&self, _: &mut Vm, _: StyleChain) -> TypResult<Template> {
- Ok(self.0.clone().styled(TextNode::STRONG, true))
+ fn show(&self, vm: &mut Vm, styles: StyleChain) -> TypResult<Template> {
+ Ok(styles
+ .show(self, vm, [Value::Template(self.0.clone())])?
+ .unwrap_or_else(|| self.0.clone().styled(TextNode::STRONG, true)))
}
}
@@ -140,8 +142,10 @@ impl EmphNode {
}
impl Show for EmphNode {
- fn show(&self, _: &mut Vm, _: StyleChain) -> TypResult<Template> {
- Ok(self.0.clone().styled(TextNode::EMPH, true))
+ fn show(&self, vm: &mut Vm, styles: StyleChain) -> TypResult<Template> {
+ Ok(styles
+ .show(self, vm, [Value::Template(self.0.clone())])?
+ .unwrap_or_else(|| self.0.clone().styled(TextNode::EMPH, true)))
}
}