summaryrefslogtreecommitdiff
path: root/library/src
diff options
context:
space:
mode:
authorLaurenz <laurmaedje@gmail.com>2023-03-19 22:28:49 +0100
committerLaurenz <laurmaedje@gmail.com>2023-03-19 22:39:19 +0100
commitab43bd802eafe33977a91893907e67553e099569 (patch)
treeaf4dead92b143348f52e2e8f869df3f7dfd7322a /library/src
parentd6aaae0cea1e79eecd85dc94ab85b9ad8eff48e8 (diff)
Renaming and refactoring
Diffstat (limited to 'library/src')
-rw-r--r--library/src/compute/construct.rs11
-rw-r--r--library/src/compute/foundations.rs2
-rw-r--r--library/src/layout/align.rs6
-rw-r--r--library/src/layout/columns.rs16
-rw-r--r--library/src/layout/container.rs30
-rw-r--r--library/src/layout/enum.rs18
-rw-r--r--library/src/layout/flow.rs86
-rw-r--r--library/src/layout/grid.rs10
-rw-r--r--library/src/layout/hide.rs8
-rw-r--r--library/src/layout/list.rs20
-rw-r--r--library/src/layout/measure.rs2
-rw-r--r--library/src/layout/mod.rs183
-rw-r--r--library/src/layout/pad.rs6
-rw-r--r--library/src/layout/page.rs18
-rw-r--r--library/src/layout/par.rs194
-rw-r--r--library/src/layout/place.rs14
-rw-r--r--library/src/layout/regions.rs4
-rw-r--r--library/src/layout/repeat.rs10
-rw-r--r--library/src/layout/spacing.rs24
-rw-r--r--library/src/layout/stack.rs23
-rw-r--r--library/src/layout/table.rs18
-rw-r--r--library/src/layout/terms.rs28
-rw-r--r--library/src/layout/transform.rs18
-rw-r--r--library/src/lib.rs170
-rw-r--r--library/src/math/accent.rs14
-rw-r--r--library/src/math/align.rs6
-rw-r--r--library/src/math/attach.rs26
-rw-r--r--library/src/math/ctx.rs50
-rw-r--r--library/src/math/delimited.rs29
-rw-r--r--library/src/math/frac.rs16
-rw-r--r--library/src/math/fragment.rs8
-rw-r--r--library/src/math/matrix.rs22
-rw-r--r--library/src/math/mod.rs137
-rw-r--r--library/src/math/op.rs14
-rw-r--r--library/src/math/root.rs40
-rw-r--r--library/src/math/row.rs6
-rw-r--r--library/src/math/spacing.rs8
-rw-r--r--library/src/math/style.rs213
-rw-r--r--library/src/math/underover.rs36
-rw-r--r--library/src/meta/bibliography.rs106
-rw-r--r--library/src/meta/context.rs20
-rw-r--r--library/src/meta/counter.rs82
-rw-r--r--library/src/meta/document.rs24
-rw-r--r--library/src/meta/figure.rs28
-rw-r--r--library/src/meta/heading.rs45
-rw-r--r--library/src/meta/link.rs40
-rw-r--r--library/src/meta/outline.rs70
-rw-r--r--library/src/meta/query.rs28
-rw-r--r--library/src/meta/reference.rs48
-rw-r--r--library/src/meta/state.rs37
-rw-r--r--library/src/prelude.rs8
-rw-r--r--library/src/shared/behave.rs33
-rw-r--r--library/src/shared/ext.rs32
-rw-r--r--library/src/symbols/emoji.rs2
-rw-r--r--library/src/text/deco.rs30
-rw-r--r--library/src/text/misc.rs36
-rw-r--r--library/src/text/mod.rs34
-rw-r--r--library/src/text/quotes.rs4
-rw-r--r--library/src/text/raw.rs41
-rw-r--r--library/src/text/shaping.rs72
-rw-r--r--library/src/text/shift.rs42
-rw-r--r--library/src/visualize/image.rs8
-rw-r--r--library/src/visualize/line.rs8
-rw-r--r--library/src/visualize/shape.rs26
64 files changed, 1196 insertions, 1252 deletions
diff --git a/library/src/compute/construct.rs b/library/src/compute/construct.rs
index 4d6068a1..a30faf2e 100644
--- a/library/src/compute/construct.rs
+++ b/library/src/compute/construct.rs
@@ -1,7 +1,6 @@
use std::num::NonZeroI64;
use std::str::FromStr;
-use ecow::EcoVec;
use typst::eval::Regex;
use crate::prelude::*;
@@ -173,12 +172,12 @@ cast_from_value! {
Component,
v: i64 => match v {
0 ..= 255 => Self(v as u8),
- _ => Err("must be between 0 and 255")?,
+ _ => Err("number must be between 0 and 255")?,
},
v: Ratio => if (0.0 ..= 1.0).contains(&v.get()) {
Self((v.get() * 255.0).round() as u8)
} else {
- Err("must be between 0% and 100%")?
+ Err("ratio must be between 0% and 100%")?
},
}
@@ -220,7 +219,7 @@ cast_from_value! {
v: Ratio => if (0.0 ..= 1.0).contains(&v.get()) {
Self((v.get() * 255.0).round() as u8)
} else {
- Err("must be between 0% and 100%")?
+ Err("ratio must be between 0% and 100%")?
},
}
@@ -258,14 +257,14 @@ pub fn symbol(
#[variadic]
variants: Vec<Spanned<Variant>>,
) -> Value {
- let mut list = EcoVec::new();
+ let mut list = Vec::new();
for Spanned { v, span } in variants {
if list.iter().any(|(prev, _)| &v.0 == prev) {
bail!(span, "duplicate variant");
}
list.push((v.0, v.1));
}
- Value::Symbol(Symbol::runtime(list))
+ Value::Symbol(Symbol::runtime(list.into_boxed_slice()))
}
/// A value that can be cast to a symbol.
diff --git a/library/src/compute/foundations.rs b/library/src/compute/foundations.rs
index 8b148c85..d5397e60 100644
--- a/library/src/compute/foundations.rs
+++ b/library/src/compute/foundations.rs
@@ -134,5 +134,5 @@ pub fn eval(
source: Spanned<String>,
) -> Value {
let Spanned { v: text, span } = source;
- typst::eval::eval_code_str(vm.world(), &text, span)?
+ typst::eval::eval_string(vm.world(), &text, span)?
}
diff --git a/library/src/layout/align.rs b/library/src/layout/align.rs
index 2a3998bf..c2f8262e 100644
--- a/library/src/layout/align.rs
+++ b/library/src/layout/align.rs
@@ -14,8 +14,8 @@ use crate::prelude::*;
///
/// Display: Align
/// Category: layout
-#[node(Show)]
-pub struct AlignNode {
+#[element(Show)]
+pub struct AlignElem {
/// The alignment along both axes.
///
/// Possible values for horizontal alignments are:
@@ -57,7 +57,7 @@ pub struct AlignNode {
pub body: Content,
}
-impl Show for AlignNode {
+impl Show for AlignElem {
fn show(&self, _: &mut Vt, styles: StyleChain) -> SourceResult<Content> {
Ok(self
.body()
diff --git a/library/src/layout/columns.rs b/library/src/layout/columns.rs
index 7704e9c4..3a1b012a 100644
--- a/library/src/layout/columns.rs
+++ b/library/src/layout/columns.rs
@@ -1,5 +1,5 @@
use crate::prelude::*;
-use crate::text::TextNode;
+use crate::text::TextElem;
/// Separate a region into multiple equally sized columns.
///
@@ -32,8 +32,8 @@ use crate::text::TextNode;
///
/// Display: Columns
/// Category: layout
-#[node(Layout)]
-pub struct ColumnsNode {
+#[element(Layout)]
+pub struct ColumnsElem {
/// The number of columns.
#[positional]
#[default(NonZeroUsize::new(2).unwrap())]
@@ -49,7 +49,7 @@ pub struct ColumnsNode {
pub body: Content,
}
-impl Layout for ColumnsNode {
+impl Layout for ColumnsElem {
fn layout(
&self,
vt: &mut Vt,
@@ -88,7 +88,7 @@ impl Layout for ColumnsNode {
let mut frames = body.layout(vt, styles, pod)?.into_iter();
let mut finished = vec![];
- let dir = TextNode::dir_in(styles);
+ let dir = TextElem::dir_in(styles);
let total_regions = (frames.len() as f32 / columns as f32).ceil() as usize;
// Stitch together the columns for each region.
@@ -151,15 +151,15 @@ impl Layout for ColumnsNode {
///
/// Display: Column Break
/// Category: layout
-#[node(Behave)]
-pub struct ColbreakNode {
+#[element(Behave)]
+pub struct ColbreakElem {
/// If `{true}`, the column break is skipped if the current column is
/// already empty.
#[default(false)]
pub weak: bool,
}
-impl Behave for ColbreakNode {
+impl Behave for ColbreakElem {
fn behaviour(&self) -> Behaviour {
if self.weak(StyleChain::default()) {
Behaviour::Weak(1)
diff --git a/library/src/layout/container.rs b/library/src/layout/container.rs
index bdc147c3..ef7def7a 100644
--- a/library/src/layout/container.rs
+++ b/library/src/layout/container.rs
@@ -1,4 +1,4 @@
-use super::VNode;
+use super::VElem;
use crate::layout::Spacing;
use crate::prelude::*;
@@ -21,8 +21,8 @@ use crate::prelude::*;
///
/// Display: Box
/// Category: layout
-#[node(Layout)]
-pub struct BoxNode {
+#[element(Layout)]
+pub struct BoxElem {
/// The width of the box.
///
/// Boxes can have [fractional]($type/fraction) widths, as the example
@@ -93,7 +93,7 @@ pub struct BoxNode {
pub body: Option<Content>,
}
-impl Layout for BoxNode {
+impl Layout for BoxElem {
fn layout(
&self,
vt: &mut Vt,
@@ -183,8 +183,8 @@ impl Layout for BoxNode {
///
/// Display: Block
/// Category: layout
-#[node(Layout)]
-pub struct BlockNode {
+#[element(Layout)]
+pub struct BlockElem {
/// The block's width.
///
/// ```example
@@ -278,11 +278,11 @@ pub struct BlockNode {
#[parse(
let spacing = args.named("spacing")?;
args.named("above")?
- .map(VNode::block_around)
- .or_else(|| spacing.map(VNode::block_spacing))
+ .map(VElem::block_around)
+ .or_else(|| spacing.map(VElem::block_spacing))
)]
- #[default(VNode::block_spacing(Em::new(1.2).into()))]
- pub above: VNode,
+ #[default(VElem::block_spacing(Em::new(1.2).into()))]
+ pub above: VElem,
/// The spacing between this block and its successor. Takes precedence
/// over `spacing`.
@@ -290,11 +290,11 @@ pub struct BlockNode {
/// The default value is `{1.2em}`.
#[parse(
args.named("below")?
- .map(VNode::block_around)
- .or_else(|| spacing.map(VNode::block_spacing))
+ .map(VElem::block_around)
+ .or_else(|| spacing.map(VElem::block_spacing))
)]
- #[default(VNode::block_spacing(Em::new(1.2).into()))]
- pub below: VNode,
+ #[default(VElem::block_spacing(Em::new(1.2).into()))]
+ pub below: VElem,
/// The contents of the block.
#[positional]
@@ -308,7 +308,7 @@ pub struct BlockNode {
pub sticky: bool,
}
-impl Layout for BlockNode {
+impl Layout for BlockElem {
fn layout(
&self,
vt: &mut Vt,
diff --git a/library/src/layout/enum.rs b/library/src/layout/enum.rs
index 05b42bd8..1be57d4c 100644
--- a/library/src/layout/enum.rs
+++ b/library/src/layout/enum.rs
@@ -1,9 +1,9 @@
use std::str::FromStr;
-use crate::layout::{BlockNode, ParNode, Sizing, Spacing};
+use crate::layout::{BlockElem, ParElem, Sizing, Spacing};
use crate::meta::{Numbering, NumberingPattern};
use crate::prelude::*;
-use crate::text::TextNode;
+use crate::text::TextElem;
use super::GridLayouter;
@@ -50,8 +50,8 @@ use super::GridLayouter;
///
/// Display: Numbered List
/// Category: layout
-#[node(Layout)]
-pub struct EnumNode {
+#[element(Layout)]
+pub struct EnumElem {
/// If this is `{false}`, the items are spaced apart with
/// [enum spacing]($func/enum.spacing). If it is `{true}`, they use normal
/// [leading]($func/par.leading) instead. This makes the enumeration more
@@ -153,7 +153,7 @@ pub struct EnumNode {
parents: Parent,
}
-impl Layout for EnumNode {
+impl Layout for EnumElem {
fn layout(
&self,
vt: &mut Vt,
@@ -164,10 +164,10 @@ impl Layout for EnumNode {
let indent = self.indent(styles);
let body_indent = self.body_indent(styles);
let gutter = if self.tight(styles) {
- ParNode::leading_in(styles).into()
+ ParElem::leading_in(styles).into()
} else {
self.spacing(styles)
- .unwrap_or_else(|| BlockNode::below_in(styles).amount())
+ .unwrap_or_else(|| BlockElem::below_in(styles).amount())
};
let mut cells = vec![];
@@ -186,7 +186,7 @@ impl Layout for EnumNode {
} else {
match &numbering {
Numbering::Pattern(pattern) => {
- TextNode::packed(pattern.apply_kth(parents.len(), number))
+ TextElem::packed(pattern.apply_kth(parents.len(), number))
}
other => other.apply_vt(vt, &[number])?.display(),
}
@@ -221,7 +221,7 @@ impl Layout for EnumNode {
///
/// Display: Numbered List Item
/// Category: layout
-#[node]
+#[element]
pub struct EnumItem {
/// The item's number.
#[positional]
diff --git a/library/src/layout/flow.rs b/library/src/layout/flow.rs
index 096c575e..b6476816 100644
--- a/library/src/layout/flow.rs
+++ b/library/src/layout/flow.rs
@@ -1,24 +1,22 @@
-use typst::model::StyledNode;
-
-use super::{AlignNode, BlockNode, ColbreakNode, ParNode, PlaceNode, Spacing, VNode};
+use super::{AlignElem, BlockElem, ColbreakElem, ParElem, PlaceElem, Spacing, VElem};
use crate::prelude::*;
-use crate::visualize::{CircleNode, EllipseNode, ImageNode, RectNode, SquareNode};
+use crate::visualize::{CircleElem, EllipseElem, ImageElem, RectElem, SquareElem};
-/// Arrange spacing, paragraphs and block-level nodes into a flow.
+/// Arrange spacing, paragraphs and block-level elements into a flow.
///
-/// This node is responsible for layouting both the top-level content flow and
+/// This element is responsible for layouting both the top-level content flow and
/// the contents of boxes.
///
/// Display: Flow
/// Category: layout
-#[node(Layout)]
-pub struct FlowNode {
+#[element(Layout)]
+pub struct FlowElem {
/// The children that will be arranges into a flow.
#[variadic]
pub children: Vec<Content>,
}
-impl Layout for FlowNode {
+impl Layout for FlowElem {
fn layout(
&self,
vt: &mut Vt,
@@ -27,29 +25,27 @@ impl Layout for FlowNode {
) -> SourceResult<Fragment> {
let mut layouter = FlowLayouter::new(regions);
- for mut child in self.children() {
- let map;
+ for mut child in &self.children() {
let outer = styles;
- let mut styles = outer;
- if let Some(node) = child.to::<StyledNode>() {
- map = node.styles();
+ let mut styles = styles;
+ if let Some((elem, map)) = child.to_styled() {
+ child = elem;
styles = outer.chain(&map);
- child = node.body();
}
- if let Some(node) = child.to::<VNode>() {
- layouter.layout_spacing(node, styles);
- } else if let Some(node) = child.to::<ParNode>() {
- layouter.layout_par(vt, node, styles)?;
- } else if child.is::<RectNode>()
- || child.is::<SquareNode>()
- || child.is::<EllipseNode>()
- || child.is::<CircleNode>()
- || child.is::<ImageNode>()
+ if let Some(elem) = child.to::<VElem>() {
+ layouter.layout_spacing(elem, styles);
+ } else if let Some(elem) = child.to::<ParElem>() {
+ layouter.layout_par(vt, elem, styles)?;
+ } else if child.is::<RectElem>()
+ || child.is::<SquareElem>()
+ || child.is::<EllipseElem>()
+ || child.is::<CircleElem>()
+ || child.is::<ImageElem>()
{
let layoutable = child.with::<dyn Layout>().unwrap();
layouter.layout_single(vt, layoutable, styles)?;
- } else if child.is::<MetaNode>() {
+ } else if child.is::<MetaElem>() {
let mut frame = Frame::new(Size::zero());
frame.meta(styles, true);
layouter.items.push(FlowItem::Frame(
@@ -59,7 +55,7 @@ impl Layout for FlowNode {
));
} else if child.can::<dyn Layout>() {
layouter.layout_multiple(vt, &child, styles)?;
- } else if child.is::<ColbreakNode>() {
+ } else if child.is::<ColbreakElem>() {
if !layouter.regions.backlog.is_empty() || layouter.regions.last.is_some()
{
layouter.finish_region();
@@ -122,13 +118,13 @@ impl<'a> FlowLayouter<'a> {
}
/// Layout vertical spacing.
- fn layout_spacing(&mut self, node: &VNode, styles: StyleChain) {
- self.layout_item(match node.amount() {
- Spacing::Rel(v) => FlowItem::Absolute(
- v.resolve(styles).relative_to(self.initial.y),
- node.weakness(styles) > 0,
+ fn layout_spacing(&mut self, v: &VElem, styles: StyleChain) {
+ self.layout_item(match v.amount() {
+ Spacing::Rel(rel) => FlowItem::Absolute(
+ rel.resolve(styles).relative_to(self.initial.y),
+ v.weakness(styles) > 0,
),
- Spacing::Fr(v) => FlowItem::Fractional(v),
+ Spacing::Fr(fr) => FlowItem::Fractional(fr),
});
}
@@ -136,11 +132,11 @@ impl<'a> FlowLayouter<'a> {
fn layout_par(
&mut self,
vt: &mut Vt,
- par: &ParNode,
+ par: &ParElem,
styles: StyleChain,
) -> SourceResult<()> {
- let aligns = AlignNode::alignment_in(styles).resolve(styles);
- let leading = ParNode::leading_in(styles);
+ let aligns = AlignElem::alignment_in(styles).resolve(styles);
+ let leading = ParElem::leading_in(styles);
let consecutive = self.last_was_par;
let frames = par
.layout(vt, styles, consecutive, self.regions.base(), self.regions.expand.x)?
@@ -185,8 +181,8 @@ impl<'a> FlowLayouter<'a> {
content: &dyn Layout,
styles: StyleChain,
) -> SourceResult<()> {
- let aligns = AlignNode::alignment_in(styles).resolve(styles);
- let sticky = BlockNode::sticky_in(styles);
+ let aligns = AlignElem::alignment_in(styles).resolve(styles);
+ let sticky = BlockElem::sticky_in(styles);
let pod = Regions::one(self.regions.base(), Axes::splat(false));
let frame = content.layout(vt, styles, pod)?.into_frame();
self.layout_item(FlowItem::Frame(frame, aligns, sticky));
@@ -201,9 +197,9 @@ impl<'a> FlowLayouter<'a> {
block: &Content,
styles: StyleChain,
) -> SourceResult<()> {
- // Placed nodes that are out of flow produce placed items which aren't
- // aligned later.
- if let Some(placed) = block.to::<PlaceNode>() {
+ // Placed elements that are out of flow produce placed items which
+ // aren't aligned later.
+ if let Some(placed) = block.to::<PlaceElem>() {
if placed.out_of_flow(styles) {
let frame = block.layout(vt, styles, self.regions)?.into_frame();
self.layout_item(FlowItem::Placed(frame));
@@ -212,17 +208,17 @@ impl<'a> FlowLayouter<'a> {
}
// How to align the block.
- let aligns = if let Some(align) = block.to::<AlignNode>() {
+ let aligns = if let Some(align) = block.to::<AlignElem>() {
align.alignment(styles)
- } else if let Some(styled) = block.to::<StyledNode>() {
- AlignNode::alignment_in(styles.chain(&styled.styles()))
+ } else if let Some((_, local)) = block.to_styled() {
+ AlignElem::alignment_in(styles.chain(local))
} else {
- AlignNode::alignment_in(styles)
+ AlignElem::alignment_in(styles)
}
.resolve(styles);
// Layout the block itself.
- let sticky = BlockNode::sticky_in(styles);
+ let sticky = BlockElem::sticky_in(styles);
let fragment = block.layout(vt, styles, self.regions)?;
for (i, frame) in fragment.into_iter().enumerate() {
if i > 0 {
diff --git a/library/src/layout/grid.rs b/library/src/layout/grid.rs
index 47d3ab86..5c3d132e 100644
--- a/library/src/layout/grid.rs
+++ b/library/src/layout/grid.rs
@@ -1,5 +1,5 @@
use crate::prelude::*;
-use crate::text::TextNode;
+use crate::text::TextElem;
use super::Sizing;
@@ -61,8 +61,8 @@ use super::Sizing;
///
/// Display: Grid
/// Category: layout
-#[node(Layout)]
-pub struct GridNode {
+#[element(Layout)]
+pub struct GridElem {
/// Defines the column sizes.
///
/// Either specify a track size array or provide an integer to create a grid
@@ -101,7 +101,7 @@ pub struct GridNode {
pub children: Vec<Content>,
}
-impl Layout for GridNode {
+impl Layout for GridElem {
fn layout(
&self,
vt: &mut Vt,
@@ -257,7 +257,7 @@ impl<'a, 'v> GridLayouter<'a, 'v> {
}
// Reverse for RTL.
- let is_rtl = TextNode::dir_in(styles) == Dir::RTL;
+ let is_rtl = TextElem::dir_in(styles) == Dir::RTL;
if is_rtl {
cols.reverse();
}
diff --git a/library/src/layout/hide.rs b/library/src/layout/hide.rs
index 1d87d3e8..d9bee317 100644
--- a/library/src/layout/hide.rs
+++ b/library/src/layout/hide.rs
@@ -15,15 +15,15 @@ use crate::prelude::*;
///
/// Display: Hide
/// Category: layout
-#[node(Show)]
-pub struct HideNode {
+#[element(Show)]
+pub struct HideElem {
/// The content to hide.
#[required]
pub body: Content,
}
-impl Show for HideNode {
+impl Show for HideElem {
fn show(&self, _: &mut Vt, _: StyleChain) -> SourceResult<Content> {
- Ok(self.body().styled(MetaNode::set_data(vec![Meta::Hide])))
+ Ok(self.body().styled(MetaElem::set_data(vec![Meta::Hide])))
}
}
diff --git a/library/src/layout/list.rs b/library/src/layout/list.rs
index fe78131d..179c93eb 100644
--- a/library/src/layout/list.rs
+++ b/library/src/layout/list.rs
@@ -1,6 +1,6 @@
-use crate::layout::{BlockNode, ParNode, Sizing, Spacing};
+use crate::layout::{BlockElem, ParElem, Sizing, Spacing};
use crate::prelude::*;
-use crate::text::TextNode;
+use crate::text::TextElem;
use super::GridLayouter;
@@ -36,8 +36,8 @@ use super::GridLayouter;
///
/// Display: Bullet List
/// Category: layout
-#[node(Layout)]
-pub struct ListNode {
+#[element(Layout)]
+pub struct ListElem {
/// If this is `{false}`, the items are spaced apart with [list
/// spacing]($func/list.spacing). If it is `{true}`, they use normal
/// [leading]($func/par.leading) instead. This makes the list more compact,
@@ -111,7 +111,7 @@ pub struct ListNode {
depth: Depth,
}
-impl Layout for ListNode {
+impl Layout for ListElem {
fn layout(
&self,
vt: &mut Vt,
@@ -121,10 +121,10 @@ impl Layout for ListNode {
let indent = self.indent(styles);
let body_indent = self.body_indent(styles);
let gutter = if self.tight(styles) {
- ParNode::leading_in(styles).into()
+ ParElem::leading_in(styles).into()
} else {
self.spacing(styles)
- .unwrap_or_else(|| BlockNode::below_in(styles).amount())
+ .unwrap_or_else(|| BlockElem::below_in(styles).amount())
};
let depth = self.depth(styles);
@@ -160,7 +160,7 @@ impl Layout for ListNode {
///
/// Display: Bullet List Item
/// Category: layout
-#[node]
+#[element]
pub struct ListItem {
/// The item's body.
#[required]
@@ -187,7 +187,7 @@ impl ListMarker {
.get(depth)
.or(list.last())
.cloned()
- .unwrap_or_else(|| TextNode::packed('•')),
+ .unwrap_or_else(|| TextElem::packed('•')),
Self::Func(func) => func.call_vt(vt, [Value::Int(depth as i64)])?.display(),
})
}
@@ -198,7 +198,7 @@ cast_from_value! {
v: Content => Self::Content(vec![v]),
array: Array => {
if array.len() == 0 {
- Err("must contain at least one marker")?;
+ Err("array must contain at least one marker")?;
}
Self::Content(array.into_iter().map(Value::display).collect())
},
diff --git a/library/src/layout/measure.rs b/library/src/layout/measure.rs
index b116cbf8..df66d67f 100644
--- a/library/src/layout/measure.rs
+++ b/library/src/layout/measure.rs
@@ -10,7 +10,7 @@ pub fn measure(
/// The content whose size to measure.
content: Content,
/// The styles with which to layout the content.
- styles: StyleMap,
+ styles: Styles,
) -> Value {
let pod = Regions::one(Axes::splat(Abs::inf()), Axes::splat(false));
let styles = StyleChain::new(&styles);
diff --git a/library/src/layout/mod.rs b/library/src/layout/mod.rs
index b6ecce51..02d3bca5 100644
--- a/library/src/layout/mod.rs
+++ b/library/src/layout/mod.rs
@@ -50,14 +50,14 @@ use std::mem;
use typed_arena::Arena;
use typst::diag::SourceResult;
use typst::eval::Tracer;
-use typst::model::{applicable, realize, SequenceNode, StyleVecBuilder, StyledNode};
+use typst::model::{applicable, realize, StyleVecBuilder};
-use crate::math::{EquationNode, LayoutMath};
-use crate::meta::DocumentNode;
+use crate::math::{EquationElem, LayoutMath};
+use crate::meta::DocumentElem;
use crate::prelude::*;
use crate::shared::BehavedBuilder;
-use crate::text::{LinebreakNode, SmartQuoteNode, SpaceNode, TextNode};
-use crate::visualize::{CircleNode, EllipseNode, ImageNode, RectNode, SquareNode};
+use crate::text::{LinebreakElem, SmartQuoteElem, SpaceElem, TextElem};
+use crate::visualize::{CircleElem, EllipseElem, ImageElem, RectElem, SquareElem};
/// Root-level layout.
pub trait LayoutRoot {
@@ -69,7 +69,7 @@ impl LayoutRoot for Content {
fn layout_root(&self, vt: &mut Vt, styles: StyleChain) -> SourceResult<Document> {
#[comemo::memoize]
fn cached(
- node: &Content,
+ content: &Content,
world: Tracked<dyn World>,
tracer: TrackedMut<Tracer>,
provider: TrackedMut<StabilityProvider>,
@@ -78,7 +78,7 @@ impl LayoutRoot for Content {
) -> SourceResult<Document> {
let mut vt = Vt { world, tracer, provider, introspector };
let scratch = Scratch::default();
- let (realized, styles) = realize_root(&mut vt, &scratch, node, styles)?;
+ let (realized, styles) = realize_root(&mut vt, &scratch, content, styles)?;
realized
.with::<dyn LayoutRoot>()
.unwrap()
@@ -108,8 +108,8 @@ pub trait Layout {
/// Layout without side effects.
///
- /// This node must be layouted again in the same order for the results to be
- /// valid.
+ /// This element must be layouted again in the same order for the results to
+ /// be valid.
fn measure(
&self,
vt: &mut Vt,
@@ -132,7 +132,7 @@ impl Layout for Content {
) -> SourceResult<Fragment> {
#[comemo::memoize]
fn cached(
- node: &Content,
+ content: &Content,
world: Tracked<dyn World>,
tracer: TrackedMut<Tracer>,
provider: TrackedMut<StabilityProvider>,
@@ -142,7 +142,7 @@ impl Layout for Content {
) -> SourceResult<Fragment> {
let mut vt = Vt { world, tracer, provider, introspector };
let scratch = Scratch::default();
- let (realized, styles) = realize_block(&mut vt, &scratch, node, styles)?;
+ let (realized, styles) = realize_block(&mut vt, &scratch, content, styles)?;
realized
.with::<dyn Layout>()
.unwrap()
@@ -161,7 +161,7 @@ impl Layout for Content {
}
}
-/// Realize into a node that is capable of root-level layout.
+/// Realize into an element that is capable of root-level layout.
fn realize_root<'a>(
vt: &mut Vt,
scratch: &'a Scratch<'a>,
@@ -176,10 +176,10 @@ fn realize_root<'a>(
builder.accept(content, styles)?;
builder.interrupt_page(Some(styles))?;
let (pages, shared) = builder.doc.unwrap().pages.finish();
- Ok((DocumentNode::new(pages.to_vec()).pack(), shared))
+ Ok((DocumentElem::new(pages.to_vec()).pack(), shared))
}
-/// Realize into a node that is capable of block-level layout.
+/// Realize into an element that is capable of block-level layout.
fn realize_block<'a>(
vt: &mut Vt,
scratch: &'a Scratch<'a>,
@@ -187,11 +187,11 @@ fn realize_block<'a>(
styles: StyleChain<'a>,
) -> SourceResult<(Content, StyleChain<'a>)> {
if content.can::<dyn Layout>()
- && !content.is::<RectNode>()
- && !content.is::<SquareNode>()
- && !content.is::<EllipseNode>()
- && !content.is::<CircleNode>()
- && !content.is::<ImageNode>()
+ && !content.is::<RectElem>()
+ && !content.is::<SquareElem>()
+ && !content.is::<EllipseElem>()
+ && !content.is::<CircleElem>()
+ && !content.is::<ImageElem>()
&& !applicable(content, styles)
{
return Ok((content.clone(), styles));
@@ -201,10 +201,10 @@ fn realize_block<'a>(
builder.accept(content, styles)?;
builder.interrupt_par()?;
let (children, shared) = builder.flow.0.finish();
- Ok((FlowNode::new(children.to_vec()).pack(), shared))
+ Ok((FlowElem::new(children.to_vec()).pack(), shared))
}
-/// Builds a document or a flow node from content.
+/// Builds a document or a flow element from content.
struct Builder<'a, 'v, 't> {
/// The virtual typesetter.
vt: &'v mut Vt<'t>,
@@ -227,7 +227,6 @@ struct Scratch<'a> {
styles: Arena<StyleChain<'a>>,
/// An arena where intermediate content resulting from show rules is stored.
content: Arena<Content>,
- maps: Arena<StyleMap>,
}
impl<'a, 'v, 't> Builder<'a, 'v, 't> {
@@ -247,19 +246,18 @@ impl<'a, 'v, 't> Builder<'a, 'v, 't> {
mut content: &'a Content,
styles: StyleChain<'a>,
) -> SourceResult<()> {
- if content.can::<dyn LayoutMath>() && !content.is::<EquationNode>() {
+ if content.can::<dyn LayoutMath>() && !content.is::<EquationElem>() {
content =
- self.scratch.content.alloc(EquationNode::new(content.clone()).pack());
+ self.scratch.content.alloc(EquationElem::new(content.clone()).pack());
}
- if let Some(styled) = content.to::<StyledNode>() {
- return self.styled(styled, styles);
+ if let Some((elem, local)) = content.to_styled() {
+ return self.styled(elem, local, styles);
}
- if let Some(seq) = content.to::<SequenceNode>() {
- for sub in seq.children() {
- let stored = self.scratch.content.alloc(sub);
- self.accept(stored, styles)?;
+ if let Some(children) = content.to_sequence() {
+ for elem in children {
+ self.accept(elem, styles)?;
}
return Ok(());
}
@@ -290,7 +288,7 @@ impl<'a, 'v, 't> Builder<'a, 'v, 't> {
}
let keep = content
- .to::<PagebreakNode>()
+ .to::<PagebreakElem>()
.map_or(false, |pagebreak| !pagebreak.weak(styles));
self.interrupt_page(keep.then(|| styles))?;
@@ -301,52 +299,55 @@ impl<'a, 'v, 't> Builder<'a, 'v, 't> {
}
}
- bail!(content.span(), "not allowed here");
+ if content.is::<PagebreakElem>() {
+ bail!(content.span(), "pagebreaks are not allowed inside of containers");
+ } else {
+ bail!(content.span(), "{} is not allowed here", content.func().name());
+ }
}
fn styled(
&mut self,
- styled: &'a StyledNode,
+ elem: &'a Content,
+ map: &'a Styles,
styles: StyleChain<'a>,
) -> SourceResult<()> {
- let map = self.scratch.maps.alloc(styled.styles());
let stored = self.scratch.styles.alloc(styles);
- let content = self.scratch.content.alloc(styled.body());
let styles = stored.chain(map);
self.interrupt_style(&map, None)?;
- self.accept(content, styles)?;
+ self.accept(elem, styles)?;
self.interrupt_style(map, Some(styles))?;
Ok(())
}
fn interrupt_style(
&mut self,
- map: &StyleMap,
- styles: Option<StyleChain<'a>>,
+ local: &Styles,
+ outer: Option<StyleChain<'a>>,
) -> SourceResult<()> {
- if let Some(Some(span)) = map.interruption::<DocumentNode>() {
+ if let Some(Some(span)) = local.interruption::<DocumentElem>() {
if self.doc.is_none() {
- bail!(span, "not allowed here");
+ bail!(span, "document set rules are not allowed inside of containers");
}
- if styles.is_none()
+ if outer.is_none()
&& (!self.flow.0.is_empty()
|| !self.par.0.is_empty()
|| !self.list.items.is_empty())
{
- bail!(span, "must appear before any content");
+ bail!(span, "document set rules must appear before any content");
}
- } else if let Some(Some(span)) = map.interruption::<PageNode>() {
+ } else if let Some(Some(span)) = local.interruption::<PageElem>() {
if self.doc.is_none() {
- bail!(span, "not allowed here");
+ bail!(span, "page configuration is not allowed inside of containers");
}
- self.interrupt_page(styles)?;
- } else if map.interruption::<ParNode>().is_some()
- || map.interruption::<AlignNode>().is_some()
+ self.interrupt_page(outer)?;
+ } else if local.interruption::<ParElem>().is_some()
+ || local.interruption::<AlignElem>().is_some()
{
self.interrupt_par()?;
- } else if map.interruption::<ListNode>().is_some()
- || map.interruption::<EnumNode>().is_some()
- || map.interruption::<TermsNode>().is_some()
+ } else if local.interruption::<ListElem>().is_some()
+ || local.interruption::<EnumElem>().is_some()
+ || local.interruption::<TermsElem>().is_some()
{
self.interrupt_list()?;
}
@@ -387,7 +388,7 @@ impl<'a, 'v, 't> Builder<'a, 'v, 't> {
} else {
shared
};
- let page = PageNode::new(FlowNode::new(flow.to_vec()).pack()).pack();
+ let page = PageElem::new(FlowElem::new(flow.to_vec()).pack()).pack();
let stored = self.scratch.content.alloc(page);
self.accept(stored, styles)?;
}
@@ -405,12 +406,12 @@ struct DocBuilder<'a> {
impl<'a> DocBuilder<'a> {
fn accept(&mut self, content: &Content, styles: StyleChain<'a>) -> bool {
- if let Some(pagebreak) = content.to::<PagebreakNode>() {
+ if let Some(pagebreak) = content.to::<PagebreakElem>() {
self.keep_next = !pagebreak.weak(styles);
return true;
}
- if content.is::<PageNode>() {
+ if content.is::<PageElem>() {
self.pages.push(content.clone(), styles);
self.keep_next = false;
return true;
@@ -432,7 +433,7 @@ struct FlowBuilder<'a>(BehavedBuilder<'a>, bool);
impl<'a> FlowBuilder<'a> {
fn accept(&mut self, content: &'a Content, styles: StyleChain<'a>) -> bool {
- if content.is::<ParbreakNode>() {
+ if content.is::<ParbreakElem>() {
self.1 = true;
return true;
}
@@ -440,33 +441,33 @@ impl<'a> FlowBuilder<'a> {
let last_was_parbreak = self.1;
self.1 = false;
- if content.is::<VNode>()
- || content.is::<ColbreakNode>()
- || content.is::<MetaNode>()
+ if content.is::<VElem>()
+ || content.is::<ColbreakElem>()
+ || content.is::<MetaElem>()
{
self.0.push(content.clone(), styles);
return true;
}
- if content.can::<dyn Layout>() || content.is::<ParNode>() {
- let is_tight_list = if let Some(node) = content.to::<ListNode>() {
- node.tight(styles)
- } else if let Some(node) = content.to::<EnumNode>() {
- node.tight(styles)
- } else if let Some(node) = content.to::<TermsNode>() {
- node.tight(styles)
+ if content.can::<dyn Layout>() || content.is::<ParElem>() {
+ let is_tight_list = if let Some(elem) = content.to::<ListElem>() {
+ elem.tight(styles)
+ } else if let Some(elem) = content.to::<EnumElem>() {
+ elem.tight(styles)
+ } else if let Some(elem) = content.to::<TermsElem>() {
+ elem.tight(styles)
} else {
false
};
if !last_was_parbreak && is_tight_list {
- let leading = ParNode::leading_in(styles);
- let spacing = VNode::list_attach(leading.into());
+ let leading = ParElem::leading_in(styles);
+ let spacing = VElem::list_attach(leading.into());
self.0.push(spacing.pack(), styles);
}
- let above = BlockNode::above_in(styles);
- let below = BlockNode::below_in(styles);
+ let above = BlockElem::above_in(styles);
+ let below = BlockElem::below_in(styles);
self.0.push(above.clone().pack(), styles);
self.0.push(content.clone(), styles);
self.0.push(below.clone().pack(), styles);
@@ -483,18 +484,18 @@ struct ParBuilder<'a>(BehavedBuilder<'a>);
impl<'a> ParBuilder<'a> {
fn accept(&mut self, content: &'a Content, styles: StyleChain<'a>) -> bool {
- if content.is::<MetaNode>() {
+ if content.is::<MetaElem>() {
if !self.0.is_basically_empty() {
self.0.push(content.clone(), styles);
return true;
}
- } else if content.is::<SpaceNode>()
- || content.is::<TextNode>()
- || content.is::<HNode>()
- || content.is::<LinebreakNode>()
- || content.is::<SmartQuoteNode>()
- || content.to::<EquationNode>().map_or(false, |node| !node.block(styles))
- || content.is::<BoxNode>()
+ } else if content.is::<SpaceElem>()
+ || content.is::<TextElem>()
+ || content.is::<HElem>()
+ || content.is::<LinebreakElem>()
+ || content.is::<SmartQuoteElem>()
+ || content.to::<EquationElem>().map_or(false, |elem| !elem.block(styles))
+ || content.is::<BoxElem>()
{
self.0.push(content.clone(), styles);
return true;
@@ -505,7 +506,7 @@ impl<'a> ParBuilder<'a> {
fn finish(self) -> (Content, StyleChain<'a>) {
let (children, shared) = self.0.finish();
- (ParNode::new(children.to_vec()).pack(), shared)
+ (ParElem::new(children.to_vec()).pack(), shared)
}
}
@@ -522,7 +523,7 @@ struct ListBuilder<'a> {
impl<'a> ListBuilder<'a> {
fn accept(&mut self, content: &'a Content, styles: StyleChain<'a>) -> bool {
if !self.items.is_empty()
- && (content.is::<SpaceNode>() || content.is::<ParbreakNode>())
+ && (content.is::<SpaceElem>() || content.is::<ParbreakElem>())
{
self.staged.push((content, styles));
return true;
@@ -533,12 +534,12 @@ impl<'a> ListBuilder<'a> {
|| content.is::<TermItem>())
&& self
.items
- .items()
+ .elems()
.next()
- .map_or(true, |first| first.id() == content.id())
+ .map_or(true, |first| first.func() == content.func())
{
self.items.push(content.clone(), styles);
- self.tight &= self.staged.drain(..).all(|(t, _)| !t.is::<ParbreakNode>());
+ self.tight &= self.staged.drain(..).all(|(t, _)| !t.is::<ParbreakElem>());
return true;
}
@@ -549,39 +550,39 @@ impl<'a> ListBuilder<'a> {
let (items, shared) = self.items.finish();
let item = items.items().next().unwrap();
let output = if item.is::<ListItem>() {
- ListNode::new(
+ ListElem::new(
items
.iter()
- .map(|(item, map)| {
+ .map(|(item, local)| {
let item = item.to::<ListItem>().unwrap();
- item.clone().with_body(item.body().styled_with_map(map.clone()))
+ item.clone().with_body(item.body().styled_with_map(local.clone()))
})
.collect::<Vec<_>>(),
)
.with_tight(self.tight)
.pack()
} else if item.is::<EnumItem>() {
- EnumNode::new(
+ EnumElem::new(
items
.iter()
- .map(|(item, map)| {
+ .map(|(item, local)| {
let item = item.to::<EnumItem>().unwrap();
- item.clone().with_body(item.body().styled_with_map(map.clone()))
+ item.clone().with_body(item.body().styled_with_map(local.clone()))
})
.collect::<Vec<_>>(),
)
.with_tight(self.tight)
.pack()
} else if item.is::<TermItem>() {
- TermsNode::new(
+ TermsElem::new(
items
.iter()
- .map(|(item, map)| {
+ .map(|(item, local)| {
let item = item.to::<TermItem>().unwrap();
item.clone()
- .with_term(item.term().styled_with_map(map.clone()))
+ .with_term(item.term().styled_with_map(local.clone()))
.with_description(
- item.description().styled_with_map(map.clone()),
+ item.description().styled_with_map(local.clone()),
)
})
.collect::<Vec<_>>(),
diff --git a/library/src/layout/pad.rs b/library/src/layout/pad.rs
index e8171560..441aa211 100644
--- a/library/src/layout/pad.rs
+++ b/library/src/layout/pad.rs
@@ -17,8 +17,8 @@ use crate::prelude::*;
///
/// Display: Padding
/// Category: layout
-#[node(Layout)]
-pub struct PadNode {
+#[element(Layout)]
+pub struct PadElem {
/// The padding at the left side.
#[parse(
let all = args.named("rest")?.or(args.find()?);
@@ -59,7 +59,7 @@ pub struct PadNode {
pub body: Content,
}
-impl Layout for PadNode {
+impl Layout for PadElem {
fn layout(
&self,
vt: &mut Vt,
diff --git a/library/src/layout/page.rs b/library/src/layout/page.rs
index 93ee08ce..a8a806ad 100644
--- a/library/src/layout/page.rs
+++ b/library/src/layout/page.rs
@@ -1,7 +1,7 @@
use std::ptr;
use std::str::FromStr;
-use super::{AlignNode, ColumnsNode};
+use super::{AlignElem, ColumnsElem};
use crate::meta::{Counter, CounterKey, Numbering};
use crate::prelude::*;
@@ -24,8 +24,8 @@ use crate::prelude::*;
///
/// Display: Page
/// Category: layout
-#[node]
-pub struct PageNode {
+#[element]
+pub struct PageElem {
/// A standard paper size to set width and height. When this is not
/// specified, Typst defaults to `{"a4"}` paper.
#[external]
@@ -270,7 +270,7 @@ pub struct PageNode {
pub body: Content,
}
-impl PageNode {
+impl PageElem {
/// Layout the page run into a sequence of frames, one per page.
pub fn layout(&self, vt: &mut Vt, styles: StyleChain) -> SourceResult<Fragment> {
// When one of the lengths is infinite the page fits its content along
@@ -296,7 +296,7 @@ impl PageNode {
// Realize columns.
let columns = self.columns(styles);
if columns.get() > 1 {
- child = ColumnsNode::new(child).with_count(columns).pack();
+ child = ColumnsElem::new(child).with_count(columns).pack();
}
// Realize margins.
@@ -356,7 +356,7 @@ impl PageNode {
let pod = Regions::one(area, Axes::splat(true));
let sub = content
.clone()
- .styled(AlignNode::set_alignment(align))
+ .styled(AlignElem::set_alignment(align))
.layout(vt, styles, pod)?
.into_frame();
if ptr::eq(marginal, &header) || ptr::eq(marginal, &background) {
@@ -387,8 +387,8 @@ impl PageNode {
///
/// Display: Page Break
/// Category: layout
-#[node]
-pub struct PagebreakNode {
+#[element]
+pub struct PagebreakElem {
/// If `{true}`, the page break is skipped if the current page is already
/// empty.
#[default(false)]
@@ -467,7 +467,7 @@ macro_rules! papers {
fn from_str(name: &str) -> Result<Self, Self::Err> {
match name.to_lowercase().as_str() {
$($pat => Ok(Self::$var),)*
- _ => Err("invalid paper name"),
+ _ => Err("unknown paper size"),
}
}
}
diff --git a/library/src/layout/par.rs b/library/src/layout/par.rs
index cef0d11c..db65b125 100644
--- a/library/src/layout/par.rs
+++ b/library/src/layout/par.rs
@@ -3,17 +3,15 @@ use unicode_bidi::{BidiInfo, Level as BidiLevel};
use unicode_script::{Script, UnicodeScript};
use xi_unicode::LineBreakIterator;
-use typst::model::StyledNode;
-
-use super::{BoxNode, HNode, Sizing, Spacing};
-use crate::layout::AlignNode;
-use crate::math::EquationNode;
+use super::{BoxElem, HElem, Sizing, Spacing};
+use crate::layout::AlignElem;
+use crate::math::EquationElem;
use crate::prelude::*;
use crate::text::{
- shape, LinebreakNode, Quoter, Quotes, ShapedText, SmartQuoteNode, SpaceNode, TextNode,
+ shape, LinebreakElem, Quoter, Quotes, ShapedText, SmartQuoteElem, SpaceElem, TextElem,
};
-/// Arrange text, spacing and inline-level nodes into a paragraph.
+/// Arrange text, spacing and inline-level elements into a paragraph.
///
/// Although this function is primarily used in set rules to affect paragraph
/// properties, it can also be used to explicitly render its argument onto a
@@ -38,8 +36,8 @@ use crate::text::{
///
/// Display: Paragraph
/// Category: layout
-#[node(Construct)]
-pub struct ParNode {
+#[element(Construct)]
+pub struct ParElem {
/// The spacing between lines.
///
/// The default value is `{0.65em}`.
@@ -110,22 +108,22 @@ pub struct ParNode {
pub children: Vec<Content>,
}
-impl Construct for ParNode {
- fn construct(_: &Vm, args: &mut Args) -> SourceResult<Content> {
+impl Construct for ParElem {
+ fn construct(_: &mut Vm, args: &mut Args) -> SourceResult<Content> {
// The paragraph constructor is special: It doesn't create a paragraph
- // node. Instead, it just ensures that the passed content lives in a
+ // element. Instead, it just ensures that the passed content lives in a
// separate paragraph and styles it.
let styles = Self::set(args)?;
let body = args.expect::<Content>("body")?;
- Ok(Content::sequence(vec![
- ParbreakNode::new().pack(),
+ Ok(Content::sequence([
+ ParbreakElem::new().pack(),
body.styled_with_map(styles),
- ParbreakNode::new().pack(),
+ ParbreakElem::new().pack(),
]))
}
}
-impl ParNode {
+impl ParElem {
/// Layout the paragraph into a collection of lines.
pub fn layout(
&self,
@@ -137,7 +135,7 @@ impl ParNode {
) -> SourceResult<Fragment> {
#[comemo::memoize]
fn cached(
- par: &ParNode,
+ par: &ParElem,
world: Tracked<dyn World>,
tracer: TrackedMut<Tracer>,
provider: TrackedMut<StabilityProvider>,
@@ -179,26 +177,6 @@ impl ParNode {
}
}
-/// A horizontal alignment.
-#[derive(Debug, Copy, Clone, Eq, PartialEq, Hash)]
-pub struct HorizontalAlign(pub GenAlign);
-
-cast_from_value! {
- HorizontalAlign,
- align: GenAlign => match align.axis() {
- Axis::X => Self(align),
- Axis::Y => Err("must be horizontal")?,
- },
-}
-
-impl Resolve for HorizontalAlign {
- type Output = Align;
-
- fn resolve(self, styles: StyleChain) -> Self::Output {
- self.0.resolve(styles)
- }
-}
-
/// How to determine line breaks in a paragraph.
#[derive(Debug, Copy, Clone, Eq, PartialEq, Hash, Cast)]
pub enum Linebreaks {
@@ -232,10 +210,10 @@ pub enum Linebreaks {
///
/// Display: Paragraph Break
/// Category: layout
-#[node(Unlabellable)]
-pub struct ParbreakNode {}
+#[element(Unlabellable)]
+pub struct ParbreakElem {}
-impl Unlabellable for ParbreakNode {}
+impl Unlabellable for ParbreakElem {}
/// Range of a substring of text.
type Range = std::ops::Range<usize>;
@@ -243,7 +221,7 @@ type Range = std::ops::Range<usize>;
// The characters by which spacing, inline content and pins are replaced in the
// paragraph's full text.
const SPACING_REPLACE: char = ' '; // Space
-const NODE_REPLACE: char = '\u{FFFC}'; // Object Replacement Character
+const OBJ_REPLACE: char = '\u{FFFC}'; // Object Replacement Character
/// A paragraph representation in which children are already layouted and text
/// is already preshaped.
@@ -254,7 +232,7 @@ const NODE_REPLACE: char = '\u{FFFC}'; // Object Replacement Character
struct Preparation<'a> {
/// Bidirectional text embedding levels for the paragraph.
bidi: BidiInfo<'a>,
- /// Text runs, spacing and layouted nodes.
+ /// Text runs, spacing and layouted elements.
items: Vec<Item<'a>>,
/// The span mapper.
spans: SpanMapper,
@@ -325,9 +303,9 @@ enum Segment<'a> {
/// Horizontal spacing between other segments.
Spacing(Spacing),
/// A mathematical equation.
- Equation(&'a EquationNode),
+ Equation(&'a EquationElem),
/// A box with arbitrary content.
- Box(&'a BoxNode, bool),
+ Box(&'a BoxElem, bool),
/// Metadata.
Meta,
}
@@ -339,7 +317,7 @@ impl Segment<'_> {
Self::Text(len) => len,
Self::Spacing(_) => SPACING_REPLACE.len_utf8(),
Self::Box(_, true) => SPACING_REPLACE.len_utf8(),
- Self::Equation(_) | Self::Box(_, _) | Self::Meta => NODE_REPLACE.len_utf8(),
+ Self::Equation(_) | Self::Box(_, _) | Self::Meta => OBJ_REPLACE.len_utf8(),
}
}
}
@@ -352,7 +330,7 @@ enum Item<'a> {
/// Absolute spacing between other items.
Absolute(Abs),
/// Fractional spacing between other items.
- Fractional(Fr, Option<(&'a BoxNode, StyleChain<'a>)>),
+ Fractional(Fr, Option<(&'a BoxElem, StyleChain<'a>)>),
/// Layouted inline-level content.
Frame(Frame),
}
@@ -371,7 +349,7 @@ impl<'a> Item<'a> {
match self {
Self::Text(shaped) => shaped.text.len(),
Self::Absolute(_) | Self::Fractional(_, _) => SPACING_REPLACE.len_utf8(),
- Self::Frame(_) => NODE_REPLACE.len_utf8(),
+ Self::Frame(_) => OBJ_REPLACE.len_utf8(),
}
}
@@ -520,7 +498,7 @@ fn collect<'a>(
let mut iter = children.iter().peekable();
if consecutive {
- let first_line_indent = ParNode::first_line_indent_in(*styles);
+ let first_line_indent = ParElem::first_line_indent_in(*styles);
if !first_line_indent.is_zero()
&& children
.iter()
@@ -529,7 +507,7 @@ fn collect<'a>(
behaved.behaviour() == Behaviour::Ignorant
}) {
None
- } else if child.is::<TextNode>() || child.is::<SmartQuoteNode>() {
+ } else if child.is::<TextElem>() || child.is::<SmartQuoteElem>() {
Some(true)
} else {
Some(false)
@@ -542,7 +520,7 @@ fn collect<'a>(
}
}
- let hang = ParNode::hanging_indent_in(*styles);
+ let hang = ParElem::hanging_indent_in(*styles);
if !hang.is_zero() {
full.push(SPACING_REPLACE);
segments.push((Segment::Spacing((-hang).into()), *styles));
@@ -551,61 +529,61 @@ fn collect<'a>(
while let Some(mut child) = iter.next() {
let outer = styles;
let mut styles = *styles;
- if let Some(node) = child.to::<StyledNode>() {
- child = Box::leak(Box::new(node.body()));
- styles = outer.chain(Box::leak(Box::new(node.styles())));
+ if let Some((elem, local)) = child.to_styled() {
+ child = elem;
+ styles = outer.chain(local);
}
- let segment = if child.is::<SpaceNode>() {
+ let segment = if child.is::<SpaceElem>() {
full.push(' ');
Segment::Text(1)
- } else if let Some(node) = child.to::<TextNode>() {
+ } else if let Some(elem) = child.to::<TextElem>() {
let prev = full.len();
- if let Some(case) = TextNode::case_in(styles) {
- full.push_str(&case.apply(&node.text()));
+ if let Some(case) = TextElem::case_in(styles) {
+ full.push_str(&case.apply(&elem.text()));
} else {
- full.push_str(&node.text());
+ full.push_str(&elem.text());
}
Segment::Text(full.len() - prev)
- } else if let Some(node) = child.to::<HNode>() {
+ } else if let Some(elem) = child.to::<HElem>() {
full.push(SPACING_REPLACE);
- Segment::Spacing(node.amount())
- } else if let Some(node) = child.to::<LinebreakNode>() {
- let c = if node.justify(styles) { '\u{2028}' } else { '\n' };
+ Segment::Spacing(elem.amount())
+ } else if let Some(elem) = child.to::<LinebreakElem>() {
+ let c = if elem.justify(styles) { '\u{2028}' } else { '\n' };
full.push(c);
Segment::Text(c.len_utf8())
- } else if let Some(node) = child.to::<SmartQuoteNode>() {
+ } else if let Some(elem) = child.to::<SmartQuoteElem>() {
let prev = full.len();
- if SmartQuoteNode::enabled_in(styles) {
- let lang = TextNode::lang_in(styles);
- let region = TextNode::region_in(styles);
+ if SmartQuoteElem::enabled_in(styles) {
+ let lang = TextElem::lang_in(styles);
+ let region = TextElem::region_in(styles);
let quotes = Quotes::from_lang(lang, region);
let peeked = iter.peek().and_then(|child| {
- if let Some(node) = child.to::<TextNode>() {
- node.text().chars().next()
- } else if child.is::<SmartQuoteNode>() {
+ if let Some(elem) = child.to::<TextElem>() {
+ elem.text().chars().next()
+ } else if child.is::<SmartQuoteElem>() {
Some('"')
- } else if child.is::<SpaceNode>() || child.is::<HNode>() {
+ } else if child.is::<SpaceElem>() || child.is::<HElem>() {
Some(SPACING_REPLACE)
} else {
- Some(NODE_REPLACE)
+ Some(OBJ_REPLACE)
}
});
- full.push_str(quoter.quote(&quotes, node.double(styles), peeked));
+ full.push_str(quoter.quote(&quotes, elem.double(styles), peeked));
} else {
- full.push(if node.double(styles) { '"' } else { '\'' });
+ full.push(if elem.double(styles) { '"' } else { '\'' });
}
Segment::Text(full.len() - prev)
- } else if let Some(node) = child.to::<EquationNode>() {
- full.push(NODE_REPLACE);
- Segment::Equation(node)
- } else if let Some(node) = child.to::<BoxNode>() {
- let frac = node.width(styles).is_fractional();
- full.push(if frac { SPACING_REPLACE } else { NODE_REPLACE });
- Segment::Box(node, frac)
- } else if child.is::<MetaNode>() {
- full.push(NODE_REPLACE);
+ } else if let Some(elem) = child.to::<EquationElem>() {
+ full.push(OBJ_REPLACE);
+ Segment::Equation(elem)
+ } else if let Some(elem) = child.to::<BoxElem>() {
+ let frac = elem.width(styles).is_fractional();
+ full.push(if frac { SPACING_REPLACE } else { OBJ_REPLACE });
+ Segment::Box(elem, frac)
+ } else if child.is::<MetaElem>() {
+ full.push(OBJ_REPLACE);
Segment::Meta
} else {
bail!(child.span(), "unexpected paragraph child");
@@ -645,7 +623,7 @@ fn prepare<'a>(
) -> SourceResult<Preparation<'a>> {
let bidi = BidiInfo::new(
text,
- match TextNode::dir_in(styles) {
+ match TextElem::dir_in(styles) {
Dir::LTR => Some(BidiLevel::ltr()),
Dir::RTL => Some(BidiLevel::rtl()),
_ => None,
@@ -674,16 +652,16 @@ fn prepare<'a>(
Segment::Equation(equation) => {
let pod = Regions::one(region, Axes::splat(false));
let mut frame = equation.layout(vt, styles, pod)?.into_frame();
- frame.translate(Point::with_y(TextNode::baseline_in(styles)));
+ frame.translate(Point::with_y(TextElem::baseline_in(styles)));
items.push(Item::Frame(frame));
}
- Segment::Box(node, _) => {
- if let Sizing::Fr(v) = node.width(styles) {
- items.push(Item::Fractional(v, Some((node, styles))));
+ Segment::Box(elem, _) => {
+ if let Sizing::Fr(v) = elem.width(styles) {
+ items.push(Item::Fractional(v, Some((elem, styles))));
} else {
let pod = Regions::one(region, Axes::splat(false));
- let mut frame = node.layout(vt, styles, pod)?.into_frame();
- frame.translate(Point::with_y(TextNode::baseline_in(styles)));
+ let mut frame = elem.layout(vt, styles, pod)?.into_frame();
+ frame.translate(Point::with_y(TextElem::baseline_in(styles)));
items.push(Item::Frame(frame));
}
}
@@ -702,11 +680,11 @@ fn prepare<'a>(
items,
spans,
styles,
- hyphenate: shared_get(styles, children, TextNode::hyphenate_in),
- lang: shared_get(styles, children, TextNode::lang_in),
- align: AlignNode::alignment_in(styles).x.resolve(styles),
- justify: ParNode::justify_in(styles),
- hang: ParNode::hanging_indent_in(styles),
+ hyphenate: shared_get(styles, children, TextElem::hyphenate_in),
+ lang: shared_get(styles, children, TextElem::lang_in),
+ align: AlignElem::alignment_in(styles).x.resolve(styles),
+ justify: ParElem::justify_in(styles),
+ hang: ParElem::hanging_indent_in(styles),
})
}
@@ -775,15 +753,15 @@ fn shared_get<'a, T: PartialEq>(
let value = getter(styles);
children
.iter()
- .filter_map(|child| child.to::<StyledNode>())
- .all(|node| getter(styles.chain(&node.styles())) == value)
+ .filter_map(|child| child.to_styled())
+ .all(|(_, local)| getter(styles.chain(&local)) == value)
.then(|| value)
}
/// Find suitable linebreaks.
fn linebreak<'a>(vt: &Vt, p: &'a Preparation<'a>, width: Abs) -> Vec<Line<'a>> {
- let linebreaks = ParNode::linebreaks_in(p.styles).unwrap_or_else(|| {
- if ParNode::justify_in(p.styles) {
+ let linebreaks = ParElem::linebreaks_in(p.styles).unwrap_or_else(|| {
+ if ParElem::justify_in(p.styles) {
Linebreaks::Optimized
} else {
Linebreaks::Simple
@@ -881,7 +859,7 @@ fn linebreak_optimized<'a>(vt: &Vt, p: &'a Preparation<'a>, width: Abs) -> Vec<L
line: line(vt, p, 0..0, false, false),
}];
- let em = TextNode::size_in(p.styles);
+ let em = TextElem::size_in(p.styles);
for (end, mandatory, hyphen) in breakpoints(p) {
let k = table.len();
@@ -1046,7 +1024,7 @@ impl Breakpoints<'_> {
.hyphenate
.or_else(|| {
let shaped = self.p.find(offset)?.text()?;
- Some(TextNode::hyphenate_in(shaped.styles))
+ Some(TextElem::hyphenate_in(shaped.styles))
})
.unwrap_or(false)
}
@@ -1055,7 +1033,7 @@ impl Breakpoints<'_> {
fn lang(&self, offset: usize) -> Option<hypher::Lang> {
let lang = self.p.lang.or_else(|| {
let shaped = self.p.find(offset)?.text()?;
- Some(TextNode::lang_in(shaped.styles))
+ Some(TextElem::lang_in(shaped.styles))
})?;
let bytes = lang.as_str().as_bytes().try_into().ok()?;
@@ -1196,7 +1174,7 @@ fn finalize(
.collect::<SourceResult<_>>()?;
// Prevent orphans.
- let leading = ParNode::leading_in(p.styles);
+ let leading = ParElem::leading_in(p.styles);
if frames.len() >= 2 && !frames[1].is_empty() {
let second = frames.remove(1);
let first = &mut frames[0];
@@ -1243,7 +1221,7 @@ fn commit(
if let Some(Item::Text(text)) = reordered.first() {
if let Some(glyph) = text.glyphs.first() {
if !text.dir.is_positive()
- && TextNode::overhang_in(text.styles)
+ && TextElem::overhang_in(text.styles)
&& (reordered.len() > 1 || text.glyphs.len() > 1)
{
let amount = overhang(glyph.c) * glyph.x_advance.at(text.size);
@@ -1257,7 +1235,7 @@ fn commit(
if let Some(Item::Text(text)) = reordered.last() {
if let Some(glyph) = text.glyphs.last() {
if text.dir.is_positive()
- && TextNode::overhang_in(text.styles)
+ && TextElem::overhang_in(text.styles)
&& (reordered.len() > 1 || text.glyphs.len() > 1)
{
let amount = overhang(glyph.c) * glyph.x_advance.at(text.size);
@@ -1295,13 +1273,13 @@ fn commit(
Item::Absolute(v) => {
offset += *v;
}
- Item::Fractional(v, node) => {
+ Item::Fractional(v, elem) => {
let amount = v.share(fr, remaining);
- if let Some((node, styles)) = node {
+ if let Some((elem, styles)) = elem {
let region = Size::new(amount, full);
let pod = Regions::one(region, Axes::new(true, false));
- let mut frame = node.layout(vt, *styles, pod)?.into_frame();
- frame.translate(Point::with_y(TextNode::baseline_in(*styles)));
+ let mut frame = elem.layout(vt, *styles, pod)?.into_frame();
+ frame.translate(Point::with_y(TextElem::baseline_in(*styles)));
push(&mut offset, frame);
} else {
offset += amount;
diff --git a/library/src/layout/place.rs b/library/src/layout/place.rs
index bfabd0f3..057278df 100644
--- a/library/src/layout/place.rs
+++ b/library/src/layout/place.rs
@@ -23,8 +23,8 @@ use crate::prelude::*;
///
/// Display: Place
/// Category: layout
-#[node(Layout, Behave)]
-pub struct PlaceNode {
+#[element(Layout, Behave)]
+pub struct PlaceElem {
/// Relative to which position in the parent container to place the content.
///
/// When an axis of the page is `{auto}` sized, all alignments relative to that
@@ -53,7 +53,7 @@ pub struct PlaceNode {
pub body: Content,
}
-impl Layout for PlaceNode {
+impl Layout for PlaceElem {
fn layout(
&self,
vt: &mut Vt,
@@ -86,16 +86,16 @@ impl Layout for PlaceNode {
}
}
-impl PlaceNode {
- /// Whether this node wants to be placed relative to its its parent's base
- /// origin. Instead of relative to the parent's current flow/cursor
+impl PlaceElem {
+ /// Whether this element wants to be placed relative to its its parent's
+ /// base origin. Instead of relative to the parent's current flow/cursor
/// position.
pub fn out_of_flow(&self, styles: StyleChain) -> bool {
self.alignment(styles).y.is_some()
}
}
-impl Behave for PlaceNode {
+impl Behave for PlaceElem {
fn behaviour(&self) -> Behaviour {
Behaviour::Ignorant
}
diff --git a/library/src/layout/regions.rs b/library/src/layout/regions.rs
index 94c81704..5a4db178 100644
--- a/library/src/layout/regions.rs
+++ b/library/src/layout/regions.rs
@@ -14,8 +14,8 @@ pub struct Regions<'a> {
/// The height of the final region that is repeated once the backlog is
/// drained. The width is the same for all regions.
pub last: Option<Abs>,
- /// Whether nodes should expand to fill the regions instead of shrinking to
- /// fit the content.
+ /// Whether elements should expand to fill the regions instead of shrinking
+ /// to fit the content.
pub expand: Axes<bool>,
}
diff --git a/library/src/layout/repeat.rs b/library/src/layout/repeat.rs
index c8f63ac3..a44bd075 100644
--- a/library/src/layout/repeat.rs
+++ b/library/src/layout/repeat.rs
@@ -1,6 +1,6 @@
use crate::prelude::*;
-use super::AlignNode;
+use super::AlignElem;
/// Repeats content to the available space.
///
@@ -23,14 +23,14 @@ use super::AlignNode;
///
/// Display: Repeat
/// Category: layout
-#[node(Layout)]
-pub struct RepeatNode {
+#[element(Layout)]
+pub struct RepeatElem {
/// The content to repeat.
#[required]
pub body: Content,
}
-impl Layout for RepeatNode {
+impl Layout for RepeatElem {
fn layout(
&self,
vt: &mut Vt,
@@ -39,7 +39,7 @@ impl Layout for RepeatNode {
) -> SourceResult<Fragment> {
let pod = Regions::one(regions.size, Axes::new(false, false));
let piece = self.body().layout(vt, styles, pod)?.into_frame();
- let align = AlignNode::alignment_in(styles).x.resolve(styles);
+ let align = AlignElem::alignment_in(styles).x.resolve(styles);
let fill = regions.size.x;
let width = piece.width();
diff --git a/library/src/layout/spacing.rs b/library/src/layout/spacing.rs
index e67fec03..9253c497 100644
--- a/library/src/layout/spacing.rs
+++ b/library/src/layout/spacing.rs
@@ -21,8 +21,8 @@ use crate::prelude::*;
///
/// Display: Spacing (H)
/// Category: layout
-#[node(Behave)]
-pub struct HNode {
+#[element(Behave)]
+pub struct HElem {
/// How much spacing to insert.
#[required]
pub amount: Spacing,
@@ -45,7 +45,7 @@ pub struct HNode {
pub weak: bool,
}
-impl Behave for HNode {
+impl Behave for HElem {
fn behaviour(&self) -> Behaviour {
if self.amount().is_fractional() {
Behaviour::Destructive
@@ -85,8 +85,8 @@ impl Behave for HNode {
///
/// Display: Spacing (V)
/// Category: layout
-#[node(Behave)]
-pub struct VNode {
+#[element(Behave)]
+pub struct VElem {
/// How much spacing to insert.
#[required]
pub amount: Spacing,
@@ -107,13 +107,13 @@ pub struct VNode {
#[external]
pub weak: bool,
- /// The node's weakness level, see also [`Behaviour`].
+ /// The elements's weakness level, see also [`Behaviour`].
#[internal]
#[parse(args.named("weak")?.map(|v: bool| v as usize))]
pub weakness: usize,
}
-impl VNode {
+impl VElem {
/// Normal strong spacing.
pub fn strong(amount: Spacing) -> Self {
Self::new(amount).with_weakness(0)
@@ -129,18 +129,18 @@ impl VNode {
Self::new(amount).with_weakness(2)
}
- /// Weak spacing with BlockNode::ABOVE/BELOW weakness.
+ /// Weak spacing with BlockElem::ABOVE/BELOW weakness.
pub fn block_around(amount: Spacing) -> Self {
Self::new(amount).with_weakness(3)
}
- /// Weak spacing with BlockNode::SPACING weakness.
+ /// Weak spacing with BlockElem::SPACING weakness.
pub fn block_spacing(amount: Spacing) -> Self {
Self::new(amount).with_weakness(4)
}
}
-impl Behave for VNode {
+impl Behave for VElem {
fn behaviour(&self) -> Behaviour {
if self.amount().is_fractional() {
Behaviour::Destructive
@@ -158,8 +158,8 @@ impl Behave for VNode {
}
cast_from_value! {
- VNode,
- v: Content => v.to::<Self>().cloned().ok_or("expected vnode")?,
+ VElem,
+ v: Content => v.to::<Self>().cloned().ok_or("expected `v` element")?,
}
/// Kinds of spacing.
diff --git a/library/src/layout/stack.rs b/library/src/layout/stack.rs
index 1dd81a60..77cd3f8f 100644
--- a/library/src/layout/stack.rs
+++ b/library/src/layout/stack.rs
@@ -1,6 +1,4 @@
-use typst::model::StyledNode;
-
-use super::{AlignNode, Spacing};
+use super::{AlignElem, Spacing};
use crate::prelude::*;
/// Arrange content and spacing horizontally or vertically.
@@ -20,8 +18,8 @@ use crate::prelude::*;
///
/// Display: Stack
/// Category: layout
-#[node(Layout)]
-pub struct StackNode {
+#[element(Layout)]
+pub struct StackElem {
/// The direction along which the items are stacked. Possible values are:
///
/// - `{ltr}`: Left to right.
@@ -39,7 +37,7 @@ pub struct StackNode {
pub children: Vec<StackChild>,
}
-impl Layout for StackNode {
+impl Layout for StackElem {
fn layout(
&self,
vt: &mut Vt,
@@ -73,7 +71,7 @@ impl Layout for StackNode {
}
}
-/// A child of a stack node.
+/// A child of a stack element.
#[derive(Hash)]
pub enum StackChild {
/// Spacing between other children.
@@ -196,14 +194,13 @@ impl<'a> StackLayouter<'a> {
self.finish_region();
}
- // Block-axis alignment of the `AlignNode` is respected
- // by the stack node.
- let aligns = if let Some(align) = block.to::<AlignNode>() {
+ // Block-axis alignment of the `AlignElement` is respected by stacks.
+ let aligns = if let Some(align) = block.to::<AlignElem>() {
align.alignment(styles)
- } else if let Some(styled) = block.to::<StyledNode>() {
- AlignNode::alignment_in(styles.chain(&styled.styles()))
+ } else if let Some((_, local)) = block.to_styled() {
+ AlignElem::alignment_in(styles.chain(&local))
} else {
- AlignNode::alignment_in(styles)
+ AlignElem::alignment_in(styles)
}
.resolve(styles);
diff --git a/library/src/layout/table.rs b/library/src/layout/table.rs
index d4b6e7d7..809c7ea7 100644
--- a/library/src/layout/table.rs
+++ b/library/src/layout/table.rs
@@ -1,4 +1,4 @@
-use crate::layout::{AlignNode, GridLayouter, TrackSizings};
+use crate::layout::{AlignElem, GridLayouter, TrackSizings};
use crate::meta::LocalName;
use crate::prelude::*;
@@ -32,8 +32,8 @@ use crate::prelude::*;
///
/// Display: Table
/// Category: layout
-#[node(Layout, LocalName)]
-pub struct TableNode {
+#[element(Layout, LocalName)]
+pub struct TableElem {
/// Defines the column sizes. See the [grid documentation]($func/grid) for
/// more information on track sizing.
pub columns: TrackSizings,
@@ -109,7 +109,7 @@ pub struct TableNode {
pub children: Vec<Content>,
}
-impl Layout for TableNode {
+impl Layout for TableElem {
fn layout(
&self,
vt: &mut Vt,
@@ -132,7 +132,7 @@ impl Layout for TableNode {
let x = i % cols;
let y = i / cols;
if let Smart::Custom(alignment) = align.resolve(vt, x, y)? {
- child = child.styled(AlignNode::set_alignment(alignment));
+ child = child.styled(AlignElem::set_alignment(alignment));
}
Ok(child)
@@ -168,7 +168,7 @@ impl Layout for TableNode {
let hline = Geometry::Line(target).stroked(stroke);
frame.prepend(
Point::new(-half, offset),
- Element::Shape(hline, self.span()),
+ FrameItem::Shape(hline, self.span()),
);
}
@@ -178,7 +178,7 @@ impl Layout for TableNode {
let vline = Geometry::Line(target).stroked(stroke);
frame.prepend(
Point::new(offset, -half),
- Element::Shape(vline, self.span()),
+ FrameItem::Shape(vline, self.span()),
);
}
}
@@ -192,7 +192,7 @@ impl Layout for TableNode {
let pos = Point::new(dx, dy);
let size = Size::new(col, row.height);
let rect = Geometry::Rect(size).filled(fill);
- frame.prepend(pos, Element::Shape(rect, self.span()));
+ frame.prepend(pos, FrameItem::Shape(rect, self.span()));
}
dy += row.height;
}
@@ -271,7 +271,7 @@ impl<T: Into<Value>> From<Celled<T>> for Value {
}
}
-impl LocalName for TableNode {
+impl LocalName for TableElem {
fn local_name(&self, lang: Lang) -> &'static str {
match lang {
Lang::GERMAN => "Tabelle",
diff --git a/library/src/layout/terms.rs b/library/src/layout/terms.rs
index 853dd32d..1200076f 100644
--- a/library/src/layout/terms.rs
+++ b/library/src/layout/terms.rs
@@ -1,7 +1,7 @@
-use super::{HNode, VNode};
-use crate::layout::{BlockNode, ParNode, Spacing};
+use super::{HElem, VElem};
+use crate::layout::{BlockElem, ParElem, Spacing};
use crate::prelude::*;
-use crate::text::{SpaceNode, TextNode};
+use crate::text::{SpaceElem, TextElem};
/// A list of terms and their descriptions.
///
@@ -22,8 +22,8 @@ use crate::text::{SpaceNode, TextNode};
///
/// Display: Term List
/// Category: layout
-#[node(Layout)]
-pub struct TermsNode {
+#[element(Layout)]
+pub struct TermsElem {
/// If this is `{false}`, the items are spaced apart with [term list
/// spacing]($func/terms.spacing). If it is `{true}`, they use normal
/// [leading]($func/par.leading) instead. This makes the term list more
@@ -76,7 +76,7 @@ pub struct TermsNode {
pub children: Vec<TermItem>,
}
-impl Layout for TermsNode {
+impl Layout for TermsElem {
fn layout(
&self,
vt: &mut Vt,
@@ -86,27 +86,27 @@ impl Layout for TermsNode {
let indent = self.indent(styles);
let hanging_indent = self.hanging_indent(styles);
let gutter = if self.tight(styles) {
- ParNode::leading_in(styles).into()
+ ParElem::leading_in(styles).into()
} else {
self.spacing(styles)
- .unwrap_or_else(|| BlockNode::below_in(styles).amount())
+ .unwrap_or_else(|| BlockElem::below_in(styles).amount())
};
let mut seq = vec![];
for (i, child) in self.children().into_iter().enumerate() {
if i > 0 {
- seq.push(VNode::new(gutter).with_weakness(1).pack());
+ seq.push(VElem::new(gutter).with_weakness(1).pack());
}
if indent.is_zero() {
- seq.push(HNode::new(indent.into()).pack());
+ seq.push(HElem::new(indent.into()).pack());
}
- seq.push((child.term() + TextNode::packed(':')).strong());
- seq.push(SpaceNode::new().pack());
+ seq.push((child.term() + TextElem::packed(':')).strong());
+ seq.push(SpaceElem::new().pack());
seq.push(child.description());
}
Content::sequence(seq)
- .styled(ParNode::set_hanging_indent(hanging_indent + indent))
+ .styled(ParElem::set_hanging_indent(hanging_indent + indent))
.layout(vt, styles, regions)
}
}
@@ -115,7 +115,7 @@ impl Layout for TermsNode {
///
/// Display: Term List Item
/// Category: layout
-#[node]
+#[element]
pub struct TermItem {
/// The term described by the list item.
#[required]
diff --git a/library/src/layout/transform.rs b/library/src/layout/transform.rs
index 2afe8201..2045e9ed 100644
--- a/library/src/layout/transform.rs
+++ b/library/src/layout/transform.rs
@@ -23,8 +23,8 @@ use crate::prelude::*;
///
/// Display: Move
/// Category: layout
-#[node(Layout)]
-pub struct MoveNode {
+#[element(Layout)]
+pub struct MoveElem {
/// The horizontal displacement of the content.
pub dx: Rel<Length>,
@@ -36,7 +36,7 @@ pub struct MoveNode {
pub body: Content,
}
-impl Layout for MoveNode {
+impl Layout for MoveElem {
fn layout(
&self,
vt: &mut Vt,
@@ -69,8 +69,8 @@ impl Layout for MoveNode {
///
/// Display: Rotate
/// Category: layout
-#[node(Layout)]
-pub struct RotateNode {
+#[element(Layout)]
+pub struct RotateElem {
/// The amount of rotation.
///
/// ```example
@@ -104,7 +104,7 @@ pub struct RotateNode {
pub body: Content,
}
-impl Layout for RotateNode {
+impl Layout for RotateElem {
fn layout(
&self,
vt: &mut Vt,
@@ -137,8 +137,8 @@ impl Layout for RotateNode {
///
/// Display: Scale
/// Category: layout
-#[node(Layout)]
-pub struct ScaleNode {
+#[element(Layout)]
+pub struct ScaleElem {
/// The horizontal scaling factor.
///
/// The body will be mirrored horizontally if the parameter is negative.
@@ -172,7 +172,7 @@ pub struct ScaleNode {
pub body: Content,
}
-impl Layout for ScaleNode {
+impl Layout for ScaleElem {
fn layout(
&self,
vt: &mut Vt,
diff --git a/library/src/lib.rs b/library/src/lib.rs
index 2f951b92..1a998700 100644
--- a/library/src/lib.rs
+++ b/library/src/lib.rs
@@ -13,7 +13,7 @@ pub mod visualize;
use typst::diag::At;
use typst::eval::{LangItems, Library, Module, Scope};
use typst::geom::{Align, Color, Dir, GenAlign, Smart};
-use typst::model::{Node, NodeId, StyleMap};
+use typst::model::{Element, Styles};
use self::layout::LayoutRoot;
@@ -30,69 +30,69 @@ fn global(math: Module, calc: Module) -> Module {
let mut global = Scope::deduplicating();
// Text.
- global.define("text", text::TextNode::id());
- global.define("linebreak", text::LinebreakNode::id());
- global.define("smartquote", text::SmartQuoteNode::id());
- global.define("strong", text::StrongNode::id());
- global.define("emph", text::EmphNode::id());
+ global.define("text", text::TextElem::func());
+ global.define("linebreak", text::LinebreakElem::func());
+ global.define("smartquote", text::SmartQuoteElem::func());
+ global.define("strong", text::StrongElem::func());
+ global.define("emph", text::EmphElem::func());
global.define("lower", text::lower);
global.define("upper", text::upper);
global.define("smallcaps", text::smallcaps);
- global.define("sub", text::SubNode::id());
- global.define("super", text::SuperNode::id());
- global.define("underline", text::UnderlineNode::id());
- global.define("strike", text::StrikeNode::id());
- global.define("overline", text::OverlineNode::id());
- global.define("raw", text::RawNode::id());
+ global.define("sub", text::SubElem::func());
+ global.define("super", text::SuperElem::func());
+ global.define("underline", text::UnderlineElem::func());
+ global.define("strike", text::StrikeElem::func());
+ global.define("overline", text::OverlineElem::func());
+ global.define("raw", text::RawElem::func());
global.define("lorem", text::lorem);
// Math.
global.define("math", math);
// Layout.
- global.define("page", layout::PageNode::id());
- global.define("pagebreak", layout::PagebreakNode::id());
- global.define("v", layout::VNode::id());
- global.define("par", layout::ParNode::id());
- global.define("parbreak", layout::ParbreakNode::id());
- global.define("h", layout::HNode::id());
- global.define("box", layout::BoxNode::id());
- global.define("block", layout::BlockNode::id());
- global.define("list", layout::ListNode::id());
- global.define("enum", layout::EnumNode::id());
- global.define("terms", layout::TermsNode::id());
- global.define("table", layout::TableNode::id());
- global.define("stack", layout::StackNode::id());
- global.define("grid", layout::GridNode::id());
- global.define("columns", layout::ColumnsNode::id());
- global.define("colbreak", layout::ColbreakNode::id());
- global.define("place", layout::PlaceNode::id());
- global.define("align", layout::AlignNode::id());
- global.define("pad", layout::PadNode::id());
- global.define("repeat", layout::RepeatNode::id());
- global.define("move", layout::MoveNode::id());
- global.define("scale", layout::ScaleNode::id());
- global.define("rotate", layout::RotateNode::id());
- global.define("hide", layout::HideNode::id());
+ global.define("page", layout::PageElem::func());
+ global.define("pagebreak", layout::PagebreakElem::func());
+ global.define("v", layout::VElem::func());
+ global.define("par", layout::ParElem::func());
+ global.define("parbreak", layout::ParbreakElem::func());
+ global.define("h", layout::HElem::func());
+ global.define("box", layout::BoxElem::func());
+ global.define("block", layout::BlockElem::func());
+ global.define("list", layout::ListElem::func());
+ global.define("enum", layout::EnumElem::func());
+ global.define("terms", layout::TermsElem::func());
+ global.define("table", layout::TableElem::func());
+ global.define("stack", layout::StackElem::func());
+ global.define("grid", layout::GridElem::func());
+ global.define("columns", layout::ColumnsElem::func());
+ global.define("colbreak", layout::ColbreakElem::func());
+ global.define("place", layout::PlaceElem::func());
+ global.define("align", layout::AlignElem::func());
+ global.define("pad", layout::PadElem::func());
+ global.define("repeat", layout::RepeatElem::func());
+ global.define("move", layout::MoveElem::func());
+ global.define("scale", layout::ScaleElem::func());
+ global.define("rotate", layout::RotateElem::func());
+ global.define("hide", layout::HideElem::func());
global.define("measure", layout::measure);
// Visualize.
- global.define("image", visualize::ImageNode::id());
- global.define("line", visualize::LineNode::id());
- global.define("rect", visualize::RectNode::id());
- global.define("square", visualize::SquareNode::id());
- global.define("ellipse", visualize::EllipseNode::id());
- global.define("circle", visualize::CircleNode::id());
+ global.define("image", visualize::ImageElem::func());
+ global.define("line", visualize::LineElem::func());
+ global.define("rect", visualize::RectElem::func());
+ global.define("square", visualize::SquareElem::func());
+ global.define("ellipse", visualize::EllipseElem::func());
+ global.define("circle", visualize::CircleElem::func());
// Meta.
- global.define("document", meta::DocumentNode::id());
- global.define("ref", meta::RefNode::id());
- global.define("link", meta::LinkNode::id());
- global.define("outline", meta::OutlineNode::id());
- global.define("heading", meta::HeadingNode::id());
- global.define("figure", meta::FigureNode::id());
- global.define("cite", meta::CiteNode::id());
- global.define("bibliography", meta::BibliographyNode::id());
+ global.define("document", meta::DocumentElem::func());
+ global.define("ref", meta::RefElem::func());
+ global.define("link", meta::LinkElem::func());
+ global.define("outline", meta::OutlineElem::func());
+ global.define("heading", meta::HeadingElem::func());
+ global.define("figure", meta::FigureElem::func());
+ global.define("cite", meta::CiteElem::func());
+ global.define("bibliography", meta::BibliographyElem::func());
global.define("locate", meta::locate);
global.define("style", meta::style);
global.define("counter", meta::counter);
@@ -166,71 +166,71 @@ fn global(math: Module, calc: Module) -> Module {
}
/// Construct the standard style map.
-fn styles() -> StyleMap {
- StyleMap::new()
+fn styles() -> Styles {
+ Styles::new()
}
/// Construct the standard lang item mapping.
fn items() -> LangItems {
LangItems {
layout: |world, content, styles| content.layout_root(world, styles),
- em: text::TextNode::size_in,
- dir: text::TextNode::dir_in,
- space: || text::SpaceNode::new().pack(),
- linebreak: || text::LinebreakNode::new().pack(),
- text: |text| text::TextNode::new(text).pack(),
- text_id: NodeId::of::<text::TextNode>(),
- text_str: |content| Some(content.to::<text::TextNode>()?.text()),
- smart_quote: |double| text::SmartQuoteNode::new().with_double(double).pack(),
- parbreak: || layout::ParbreakNode::new().pack(),
- strong: |body| text::StrongNode::new(body).pack(),
- emph: |body| text::EmphNode::new(body).pack(),
+ em: text::TextElem::size_in,
+ dir: text::TextElem::dir_in,
+ space: || text::SpaceElem::new().pack(),
+ linebreak: || text::LinebreakElem::new().pack(),
+ text: |text| text::TextElem::new(text).pack(),
+ text_func: text::TextElem::func(),
+ text_str: |content| Some(content.to::<text::TextElem>()?.text()),
+ smart_quote: |double| text::SmartQuoteElem::new().with_double(double).pack(),
+ parbreak: || layout::ParbreakElem::new().pack(),
+ strong: |body| text::StrongElem::new(body).pack(),
+ emph: |body| text::EmphElem::new(body).pack(),
raw: |text, lang, block| {
- let mut node = text::RawNode::new(text).with_block(block);
+ let mut elem = text::RawElem::new(text).with_block(block);
if let Some(lang) = lang {
- node.push_lang(Some(lang));
+ elem.push_lang(Some(lang));
}
- node.pack()
+ elem.pack()
},
- raw_languages: text::RawNode::languages,
- link: |url| meta::LinkNode::from_url(url).pack(),
+ raw_languages: text::RawElem::languages,
+ link: |url| meta::LinkElem::from_url(url).pack(),
reference: |target, supplement| {
- let mut node = meta::RefNode::new(target);
+ let mut elem = meta::RefElem::new(target);
if let Some(supplement) = supplement {
- node.push_supplement(Smart::Custom(Some(meta::Supplement::Content(
+ elem.push_supplement(Smart::Custom(Some(meta::Supplement::Content(
supplement,
))));
}
- node.pack()
+ elem.pack()
},
- bibliography_keys: meta::BibliographyNode::keys,
- heading: |level, title| meta::HeadingNode::new(title).with_level(level).pack(),
+ bibliography_keys: meta::BibliographyElem::keys,
+ heading: |level, title| meta::HeadingElem::new(title).with_level(level).pack(),
list_item: |body| layout::ListItem::new(body).pack(),
enum_item: |number, body| {
- let mut node = layout::EnumItem::new(body);
+ let mut elem = layout::EnumItem::new(body);
if let Some(number) = number {
- node.push_number(Some(number));
+ elem.push_number(Some(number));
}
- node.pack()
+ elem.pack()
},
term_item: |term, description| layout::TermItem::new(term, description).pack(),
- equation: |body, block| math::EquationNode::new(body).with_block(block).pack(),
- math_align_point: || math::AlignPointNode::new().pack(),
- math_delimited: |open, body, close| math::LrNode::new(open + body + close).pack(),
+ equation: |body, block| math::EquationElem::new(body).with_block(block).pack(),
+ math_align_point: || math::AlignPointElem::new().pack(),
+ math_delimited: |open, body, close| math::LrElem::new(open + body + close).pack(),
math_attach: |base, bottom, top| {
- let mut node = math::AttachNode::new(base);
+ let mut elem = math::AttachElem::new(base);
if let Some(bottom) = bottom {
- node.push_bottom(Some(bottom));
+ elem.push_bottom(Some(bottom));
}
if let Some(top) = top {
- node.push_top(Some(top));
+ elem.push_top(Some(top));
}
- node.pack()
+ elem.pack()
},
math_accent: |base, accent| {
- math::AccentNode::new(base, math::Accent::new(accent)).pack()
+ math::AccentElem::new(base, math::Accent::new(accent)).pack()
},
- math_frac: |num, denom| math::FracNode::new(num, denom).pack(),
+ math_frac: |num, denom| math::FracElem::new(num, denom).pack(),
library_method: |vm, dynamic, method, args, span| {
if let Some(counter) = dynamic.downcast::<meta::Counter>().cloned() {
counter.call_method(vm, method, args, span)
diff --git a/library/src/math/accent.rs b/library/src/math/accent.rs
index 9ef76279..471507c5 100644
--- a/library/src/math/accent.rs
+++ b/library/src/math/accent.rs
@@ -1,5 +1,3 @@
-use typst::eval::combining_accent;
-
use super::*;
/// How much the accent can be shorter than the base.
@@ -16,8 +14,8 @@ const ACCENT_SHORT_FALL: Em = Em::new(0.5);
///
/// Display: Accent
/// Category: math
-#[node(LayoutMath)]
-pub struct AccentNode {
+#[element(LayoutMath)]
+pub struct AccentElem {
/// The base to which the accent is applied.
/// May consist of multiple letters.
///
@@ -50,7 +48,7 @@ pub struct AccentNode {
pub accent: Accent,
}
-impl LayoutMath for AccentNode {
+impl LayoutMath for AccentElem {
fn layout_math(&self, ctx: &mut MathContext) -> SourceResult<()> {
ctx.style(ctx.style.with_cramped(true));
let base = ctx.layout_fragment(&self.base())?;
@@ -116,15 +114,15 @@ pub struct Accent(char);
impl Accent {
/// Normalize a character into an accent.
pub fn new(c: char) -> Self {
- Self(combining_accent(c).unwrap_or(c))
+ Self(Symbol::combining_accent(c).unwrap_or(c))
}
}
cast_from_value! {
Accent,
v: char => Self::new(v),
- v: Content => match v.to::<TextNode>() {
- Some(node) => Value::Str(node.text().into()).cast()?,
+ v: Content => match v.to::<TextElem>() {
+ Some(elem) => Value::Str(elem.text().into()).cast()?,
None => Err("expected text")?,
},
}
diff --git a/library/src/math/align.rs b/library/src/math/align.rs
index 6cf13a0f..d34379e2 100644
--- a/library/src/math/align.rs
+++ b/library/src/math/align.rs
@@ -4,10 +4,10 @@ use super::*;
///
/// Display: Alignment Point
/// Category: math
-#[node(LayoutMath)]
-pub struct AlignPointNode {}
+#[element(LayoutMath)]
+pub struct AlignPointElem {}
-impl LayoutMath for AlignPointNode {
+impl LayoutMath for AlignPointElem {
fn layout_math(&self, ctx: &mut MathContext) -> SourceResult<()> {
ctx.push(MathFragment::Align);
Ok(())
diff --git a/library/src/math/attach.rs b/library/src/math/attach.rs
index 7d8749f2..1b315f77 100644
--- a/library/src/math/attach.rs
+++ b/library/src/math/attach.rs
@@ -13,8 +13,8 @@ use super::*;
///
/// Display: Attachment
/// Category: math
-#[node(LayoutMath)]
-pub struct AttachNode {
+#[element(LayoutMath)]
+pub struct AttachElem {
/// The base to which things are attached.
#[required]
pub base: Content,
@@ -26,25 +26,25 @@ pub struct AttachNode {
pub bottom: Option<Content>,
}
-impl LayoutMath for AttachNode {
+impl LayoutMath for AttachElem {
fn layout_math(&self, ctx: &mut MathContext) -> SourceResult<()> {
let base = self.base();
- let display_limits = base.is::<LimitsNode>();
- let display_scripts = base.is::<ScriptsNode>();
+ let display_limits = base.is::<LimitsElem>();
+ let display_scripts = base.is::<ScriptsElem>();
let base = ctx.layout_fragment(&base)?;
ctx.style(ctx.style.for_subscript());
let top = self
.top(ctx.styles())
- .map(|node| ctx.layout_fragment(&node))
+ .map(|elem| ctx.layout_fragment(&elem))
.transpose()?;
ctx.unstyle();
ctx.style(ctx.style.for_superscript());
let bottom = self
.bottom(ctx.styles())
- .map(|node| ctx.layout_fragment(&node))
+ .map(|elem| ctx.layout_fragment(&elem))
.transpose()?;
ctx.unstyle();
@@ -75,14 +75,14 @@ impl LayoutMath for AttachNode {
///
/// Display: Scripts
/// Category: math
-#[node(LayoutMath)]
-pub struct ScriptsNode {
+#[element(LayoutMath)]
+pub struct ScriptsElem {
/// The base to attach the scripts to.
#[required]
pub body: Content,
}
-impl LayoutMath for ScriptsNode {
+impl LayoutMath for ScriptsElem {
fn layout_math(&self, ctx: &mut MathContext) -> SourceResult<()> {
self.body().layout_math(ctx)
}
@@ -97,14 +97,14 @@ impl LayoutMath for ScriptsNode {
///
/// Display: Limits
/// Category: math
-#[node(LayoutMath)]
-pub struct LimitsNode {
+#[element(LayoutMath)]
+pub struct LimitsElem {
/// The base to attach the limits to.
#[required]
pub body: Content,
}
-impl LayoutMath for LimitsNode {
+impl LayoutMath for LimitsElem {
fn layout_math(&self, ctx: &mut MathContext) -> SourceResult<()> {
self.body().layout_math(ctx)
}
diff --git a/library/src/math/ctx.rs b/library/src/math/ctx.rs
index bd44546d..aed826b5 100644
--- a/library/src/math/ctx.rs
+++ b/library/src/math/ctx.rs
@@ -32,7 +32,7 @@ pub struct MathContext<'a, 'b, 'v> {
pub constants: ttf_parser::math::Constants<'a>,
pub space_width: Em,
pub fragments: Vec<MathFragment>,
- pub map: StyleMap,
+ pub local: Styles,
pub style: MathStyle,
pub size: Abs,
outer: StyleChain<'a>,
@@ -49,7 +49,7 @@ impl<'a, 'b, 'v> MathContext<'a, 'b, 'v> {
) -> Self {
let table = font.ttf().tables().math.unwrap();
let constants = table.constants.unwrap();
- let size = TextNode::size_in(styles);
+ let size = TextElem::size_in(styles);
let ttf = font.ttf();
let space_width = ttf
.glyph_index(' ')
@@ -67,7 +67,7 @@ impl<'a, 'b, 'v> MathContext<'a, 'b, 'v> {
constants,
space_width,
fragments: vec![],
- map: StyleMap::new(),
+ local: Styles::new(),
style: MathStyle {
variant: MathVariant::Serif,
size: if block { MathSize::Display } else { MathSize::Text },
@@ -94,39 +94,39 @@ impl<'a, 'b, 'v> MathContext<'a, 'b, 'v> {
pub fn layout_fragment(
&mut self,
- node: &dyn LayoutMath,
+ elem: &dyn LayoutMath,
) -> SourceResult<MathFragment> {
- let row = self.layout_fragments(node)?;
+ let row = self.layout_fragments(elem)?;
Ok(MathRow::new(row).to_fragment(self))
}
pub fn layout_fragments(
&mut self,
- node: &dyn LayoutMath,
+ elem: &dyn LayoutMath,
) -> SourceResult<Vec<MathFragment>> {
let prev = std::mem::take(&mut self.fragments);
- node.layout_math(self)?;
+ elem.layout_math(self)?;
Ok(std::mem::replace(&mut self.fragments, prev))
}
- pub fn layout_row(&mut self, node: &dyn LayoutMath) -> SourceResult<MathRow> {
- let fragments = self.layout_fragments(node)?;
+ pub fn layout_row(&mut self, elem: &dyn LayoutMath) -> SourceResult<MathRow> {
+ let fragments = self.layout_fragments(elem)?;
Ok(MathRow::new(fragments))
}
- pub fn layout_frame(&mut self, node: &dyn LayoutMath) -> SourceResult<Frame> {
- Ok(self.layout_fragment(node)?.to_frame())
+ pub fn layout_frame(&mut self, elem: &dyn LayoutMath) -> SourceResult<Frame> {
+ Ok(self.layout_fragment(elem)?.to_frame())
}
pub fn layout_content(&mut self, content: &Content) -> SourceResult<Frame> {
Ok(content
- .layout(&mut self.vt, self.outer.chain(&self.map), self.regions)?
+ .layout(&mut self.vt, self.outer.chain(&self.local), self.regions)?
.into_frame())
}
- pub fn layout_text(&mut self, node: &TextNode) -> SourceResult<()> {
- let text = node.text();
- let span = node.span();
+ pub fn layout_text(&mut self, elem: &TextElem) -> SourceResult<()> {
+ let text = elem.text();
+ let span = elem.span();
let mut chars = text.chars();
if let Some(glyph) = chars
.next()
@@ -160,7 +160,7 @@ impl<'a, 'b, 'v> MathContext<'a, 'b, 'v> {
style = style.with_italic(false);
}
let text: EcoString = text.chars().map(|c| style.styled_char(c)).collect();
- let frame = self.layout_content(&TextNode::packed(text).spanned(span))?;
+ let frame = self.layout_content(&TextElem::packed(text).spanned(span))?;
self.push(
FrameFragment::new(self, frame)
.with_class(MathClass::Alphabetic)
@@ -172,21 +172,21 @@ impl<'a, 'b, 'v> MathContext<'a, 'b, 'v> {
}
pub fn styles(&self) -> StyleChain {
- self.outer.chain(&self.map)
+ self.outer.chain(&self.local)
}
pub fn style(&mut self, style: MathStyle) {
self.style_stack.push((self.style, self.size));
- let base_size = TextNode::size_in(self.styles()) / self.style.size.factor(self);
+ let base_size = TextElem::size_in(self.styles()) / self.style.size.factor(self);
self.size = base_size * style.size.factor(self);
- self.map.set(TextNode::set_size(TextSize(self.size.into())));
- self.map
- .set(TextNode::set_style(if style.italic == Smart::Custom(true) {
+ self.local.set(TextElem::set_size(TextSize(self.size.into())));
+ self.local
+ .set(TextElem::set_style(if style.italic == Smart::Custom(true) {
FontStyle::Italic
} else {
FontStyle::Normal
}));
- self.map.set(TextNode::set_weight(if style.bold {
+ self.local.set(TextElem::set_weight(if style.bold {
FontWeight::BOLD
} else {
FontWeight::REGULAR
@@ -196,9 +196,9 @@ impl<'a, 'b, 'v> MathContext<'a, 'b, 'v> {
pub fn unstyle(&mut self) {
(self.style, self.size) = self.style_stack.pop().unwrap();
- self.map.unset();
- self.map.unset();
- self.map.unset();
+ self.local.unset();
+ self.local.unset();
+ self.local.unset();
}
}
diff --git a/library/src/math/delimited.rs b/library/src/math/delimited.rs
index 2b9ee5ed..3be17eae 100644
--- a/library/src/math/delimited.rs
+++ b/library/src/math/delimited.rs
@@ -16,8 +16,8 @@ pub(super) const DELIM_SHORT_FALL: Em = Em::new(0.1);
///
/// Display: Left/Right
/// Category: math
-#[node(LayoutMath)]
-pub struct LrNode {
+#[element(LayoutMath)]
+pub struct LrElem {
/// The size of the brackets, relative to the height of the wrapped content.
///
/// Defaults to `{100%}`.
@@ -29,7 +29,7 @@ pub struct LrNode {
let mut body = Content::empty();
for (i, arg) in args.all::<Content>()?.into_iter().enumerate() {
if i > 0 {
- body += TextNode::packed(',');
+ body += TextElem::packed(',');
}
body += arg;
}
@@ -38,12 +38,12 @@ pub struct LrNode {
pub body: Content,
}
-impl LayoutMath for LrNode {
+impl LayoutMath for LrElem {
fn layout_math(&self, ctx: &mut MathContext) -> SourceResult<()> {
let mut body = self.body();
- if let Some(node) = body.to::<LrNode>() {
- if node.size(ctx.styles()).is_auto() {
- body = node.body();
+ if let Some(elem) = body.to::<LrElem>() {
+ if elem.size(ctx.styles()).is_auto() {
+ body = elem.body();
}
}
@@ -179,12 +179,11 @@ pub fn norm(
}
fn delimited(body: Content, left: char, right: char) -> Value {
- Value::Content(
- LrNode::new(Content::sequence(vec![
- TextNode::packed(left),
- body,
- TextNode::packed(right),
- ]))
- .pack(),
- )
+ LrElem::new(Content::sequence([
+ TextElem::packed(left),
+ body,
+ TextElem::packed(right),
+ ]))
+ .pack()
+ .into()
}
diff --git a/library/src/math/frac.rs b/library/src/math/frac.rs
index 90bc69b3..f19fb32e 100644
--- a/library/src/math/frac.rs
+++ b/library/src/math/frac.rs
@@ -19,8 +19,8 @@ const FRAC_AROUND: Em = Em::new(0.1);
///
/// Display: Fraction
/// Category: math
-#[node(LayoutMath)]
-pub struct FracNode {
+#[element(LayoutMath)]
+pub struct FracElem {
/// The fraction's numerator.
#[required]
pub num: Content,
@@ -30,7 +30,7 @@ pub struct FracNode {
pub denom: Content,
}
-impl LayoutMath for FracNode {
+impl LayoutMath for FracElem {
fn layout_math(&self, ctx: &mut MathContext) -> SourceResult<()> {
layout(ctx, &self.num(), &self.denom(), false, self.span())
}
@@ -45,8 +45,8 @@ impl LayoutMath for FracNode {
///
/// Display: Binomial
/// Category: math
-#[node(LayoutMath)]
-pub struct BinomNode {
+#[element(LayoutMath)]
+pub struct BinomElem {
/// The binomial's upper index.
#[required]
pub upper: Content,
@@ -56,7 +56,7 @@ pub struct BinomNode {
pub lower: Content,
}
-impl LayoutMath for BinomNode {
+impl LayoutMath for BinomElem {
fn layout_math(&self, ctx: &mut MathContext) -> SourceResult<()> {
layout(ctx, &self.upper(), &self.lower(), true, self.span())
}
@@ -132,9 +132,9 @@ fn layout(
} else {
frame.push(
line_pos,
- Element::Shape(
+ FrameItem::Shape(
Geometry::Line(Point::with_x(line_width)).stroked(Stroke {
- paint: TextNode::fill_in(ctx.styles()),
+ paint: TextElem::fill_in(ctx.styles()),
thickness,
}),
span,
diff --git a/library/src/math/fragment.rs b/library/src/math/fragment.rs
index 87e28555..0d663d3f 100644
--- a/library/src/math/fragment.rs
+++ b/library/src/math/fragment.rs
@@ -181,8 +181,8 @@ impl GlyphFragment {
id,
c,
font: ctx.font.clone(),
- lang: TextNode::lang_in(ctx.styles()),
- fill: TextNode::fill_in(ctx.styles()),
+ lang: TextElem::lang_in(ctx.styles()),
+ fill: TextElem::fill_in(ctx.styles()),
style: ctx.style,
font_size: ctx.size,
width,
@@ -215,7 +215,7 @@ impl GlyphFragment {
}
pub fn to_frame(&self) -> Frame {
- let text = Text {
+ let item = TextItem {
font: self.font.clone(),
size: self.font_size,
fill: self.fill,
@@ -232,7 +232,7 @@ impl GlyphFragment {
let size = Size::new(self.width, self.ascent + self.descent);
let mut frame = Frame::new(size);
frame.set_baseline(self.ascent);
- frame.push(Point::with_y(self.ascent), Element::Text(text));
+ frame.push(Point::with_y(self.ascent), FrameItem::Text(item));
frame
}
}
diff --git a/library/src/math/matrix.rs b/library/src/math/matrix.rs
index d79c7ca5..8fba10e7 100644
--- a/library/src/math/matrix.rs
+++ b/library/src/math/matrix.rs
@@ -16,8 +16,8 @@ const VERTICAL_PADDING: Ratio = Ratio::new(0.1);
///
/// Display: Vector
/// Category: math
-#[node(LayoutMath)]
-pub struct VecNode {
+#[element(LayoutMath)]
+pub struct VecElem {
/// The delimiter to use.
///
/// ```example
@@ -32,7 +32,7 @@ pub struct VecNode {
pub children: Vec<Content>,
}
-impl LayoutMath for VecNode {
+impl LayoutMath for VecElem {
fn layout_math(&self, ctx: &mut MathContext) -> SourceResult<()> {
let delim = self.delim(ctx.styles());
let frame = layout_vec_body(ctx, &self.children(), Align::Center)?;
@@ -68,8 +68,8 @@ impl LayoutMath for VecNode {
///
/// Display: Matrix
/// Category: math
-#[node(LayoutMath)]
-pub struct MatNode {
+#[element(LayoutMath)]
+pub struct MatElem {
/// The delimiter to use.
///
/// ```example
@@ -114,7 +114,7 @@ pub struct MatNode {
pub rows: Vec<Vec<Content>>,
}
-impl LayoutMath for MatNode {
+impl LayoutMath for MatElem {
fn layout_math(&self, ctx: &mut MathContext) -> SourceResult<()> {
let delim = self.delim(ctx.styles());
let frame = layout_mat_body(ctx, &self.rows())?;
@@ -144,8 +144,8 @@ impl LayoutMath for MatNode {
///
/// Display: Cases
/// Category: math
-#[node(LayoutMath)]
-pub struct CasesNode {
+#[element(LayoutMath)]
+pub struct CasesElem {
/// The delimiter to use.
///
/// ```example
@@ -160,7 +160,7 @@ pub struct CasesNode {
pub children: Vec<Content>,
}
-impl LayoutMath for CasesNode {
+impl LayoutMath for CasesElem {
fn layout_math(&self, ctx: &mut MathContext) -> SourceResult<()> {
let delim = self.delim(ctx.styles());
let frame = layout_vec_body(ctx, &self.children(), Align::Left)?;
@@ -221,8 +221,8 @@ fn layout_vec_body(
let gap = ROW_GAP.scaled(ctx);
ctx.style(ctx.style.for_denominator());
let mut flat = vec![];
- for element in column {
- flat.push(ctx.layout_row(element)?);
+ for child in column {
+ flat.push(ctx.layout_row(child)?);
}
ctx.unstyle();
Ok(stack(ctx, flat, align, gap, 0))
diff --git a/library/src/math/mod.rs b/library/src/math/mod.rs
index 7fb1aadf..cf665203 100644
--- a/library/src/math/mod.rs
+++ b/library/src/math/mod.rs
@@ -31,69 +31,69 @@ pub use self::underover::*;
use ttf_parser::{GlyphId, Rect};
use typst::eval::{Module, Scope};
use typst::font::{Font, FontWeight};
-use typst::model::{Guard, SequenceNode, StyledNode};
+use typst::model::Guard;
use unicode_math_class::MathClass;
use self::ctx::*;
use self::fragment::*;
use self::row::*;
use self::spacing::*;
-use crate::layout::{HNode, ParNode, Spacing};
+use crate::layout::{HElem, ParElem, Spacing};
use crate::meta::{Count, Counter, CounterUpdate, LocalName, Numbering};
use crate::prelude::*;
use crate::text::{
- families, variant, FontFamily, FontList, LinebreakNode, SpaceNode, TextNode, TextSize,
+ families, variant, FontFamily, FontList, LinebreakElem, SpaceElem, TextElem, TextSize,
};
/// Create a module with all math definitions.
pub fn module() -> Module {
let mut math = Scope::deduplicating();
- math.define("equation", EquationNode::id());
- math.define("text", TextNode::id());
+ math.define("equation", EquationElem::func());
+ math.define("text", TextElem::func());
// Grouping.
- math.define("lr", LrNode::id());
+ math.define("lr", LrElem::func());
math.define("abs", abs);
math.define("norm", norm);
math.define("floor", floor);
math.define("ceil", ceil);
// Attachments and accents.
- math.define("attach", AttachNode::id());
- math.define("scripts", ScriptsNode::id());
- math.define("limits", LimitsNode::id());
- math.define("accent", AccentNode::id());
- math.define("underline", UnderlineNode::id());
- math.define("overline", OverlineNode::id());
- math.define("underbrace", UnderbraceNode::id());
- math.define("overbrace", OverbraceNode::id());
- math.define("underbracket", UnderbracketNode::id());
- math.define("overbracket", OverbracketNode::id());
+ math.define("attach", AttachElem::func());
+ math.define("scripts", ScriptsElem::func());
+ math.define("limits", LimitsElem::func());
+ math.define("accent", AccentElem::func());
+ math.define("underline", UnderlineElem::func());
+ math.define("overline", OverlineElem::func());
+ math.define("underbrace", UnderbraceElem::func());
+ math.define("overbrace", OverbraceElem::func());
+ math.define("underbracket", UnderbracketElem::func());
+ math.define("overbracket", OverbracketElem::func());
// Fractions and matrix-likes.
- math.define("frac", FracNode::id());
- math.define("binom", BinomNode::id());
- math.define("vec", VecNode::id());
- math.define("mat", MatNode::id());
- math.define("cases", CasesNode::id());
+ math.define("frac", FracElem::func());
+ math.define("binom", BinomElem::func());
+ math.define("vec", VecElem::func());
+ math.define("mat", MatElem::func());
+ math.define("cases", CasesElem::func());
// Roots.
- math.define("sqrt", SqrtNode::id());
- math.define("root", RootNode::id());
+ math.define("sqrt", sqrt);
+ math.define("root", RootElem::func());
// Styles.
- math.define("upright", UprightNode::id());
- math.define("bold", BoldNode::id());
- math.define("italic", ItalicNode::id());
- math.define("serif", SerifNode::id());
- math.define("sans", SansNode::id());
- math.define("cal", CalNode::id());
- math.define("frak", FrakNode::id());
- math.define("mono", MonoNode::id());
- math.define("bb", BbNode::id());
+ math.define("upright", upright);
+ math.define("bold", bold);
+ math.define("italic", italic);
+ math.define("serif", serif);
+ math.define("sans", sans);
+ math.define("cal", cal);
+ math.define("frak", frak);
+ math.define("mono", mono);
+ math.define("bb", bb);
// Text operators.
- math.define("op", OpNode::id());
+ math.define("op", OpElem::func());
op::define(&mut math);
// Spacings.
@@ -133,8 +133,8 @@ pub fn module() -> Module {
///
/// Display: Equation
/// Category: math
-#[node(Locatable, Synthesize, Show, Finalize, Layout, LayoutMath, Count, LocalName)]
-pub struct EquationNode {
+#[element(Locatable, Synthesize, Show, Finalize, Layout, LayoutMath, Count, LocalName)]
+pub struct EquationElem {
/// Whether the equation is displayed as a separate block.
#[default(false)]
pub block: bool,
@@ -157,16 +157,16 @@ pub struct EquationNode {
pub body: Content,
}
-impl Synthesize for EquationNode {
+impl Synthesize for EquationElem {
fn synthesize(&mut self, _: &Vt, styles: StyleChain) {
self.push_block(self.block(styles));
self.push_numbering(self.numbering(styles));
}
}
-impl Show for EquationNode {
+impl Show for EquationElem {
fn show(&self, _: &mut Vt, styles: StyleChain) -> SourceResult<Content> {
- let mut realized = self.clone().pack().guarded(Guard::Base(NodeId::of::<Self>()));
+ let mut realized = self.clone().pack().guarded(Guard::Base(Self::func()));
if self.block(styles) {
realized = realized.aligned(Axes::with_x(Some(Align::Center.into())))
}
@@ -174,17 +174,17 @@ impl Show for EquationNode {
}
}
-impl Finalize for EquationNode {
+impl Finalize for EquationElem {
fn finalize(&self, realized: Content, _: StyleChain) -> Content {
realized
- .styled(TextNode::set_weight(FontWeight::from_number(450)))
- .styled(TextNode::set_font(FontList(vec![FontFamily::new(
+ .styled(TextElem::set_weight(FontWeight::from_number(450)))
+ .styled(TextElem::set_font(FontList(vec![FontFamily::new(
"New Computer Modern Math",
)])))
}
}
-impl Layout for EquationNode {
+impl Layout for EquationElem {
fn layout(
&self,
vt: &mut Vt,
@@ -215,7 +215,7 @@ impl Layout for EquationNode {
if block {
if let Some(numbering) = self.numbering(styles) {
let pod = Regions::one(regions.base(), Axes::splat(false));
- let counter = Counter::of(Self::id())
+ let counter = Counter::of(Self::func())
.display(numbering, false)
.layout(vt, styles, pod)?
.into_frame();
@@ -230,7 +230,7 @@ impl Layout for EquationNode {
let height = frame.height().max(counter.height());
frame.resize(Size::new(width, height), Align::CENTER_HORIZON);
- let x = if TextNode::dir_in(styles).is_positive() {
+ let x = if TextElem::dir_in(styles).is_positive() {
frame.width() - counter.width()
} else {
Abs::zero()
@@ -240,10 +240,10 @@ impl Layout for EquationNode {
frame.push_frame(Point::new(x, y), counter)
}
} else {
- let slack = ParNode::leading_in(styles) * 0.7;
- let top_edge = TextNode::top_edge_in(styles).resolve(styles, font.metrics());
+ let slack = ParElem::leading_in(styles) * 0.7;
+ let top_edge = TextElem::top_edge_in(styles).resolve(styles, font.metrics());
let bottom_edge =
- -TextNode::bottom_edge_in(styles).resolve(styles, font.metrics());
+ -TextElem::bottom_edge_in(styles).resolve(styles, font.metrics());
let ascent = top_edge.max(frame.ascent() - slack);
let descent = bottom_edge.max(frame.descent() - slack);
@@ -255,7 +255,7 @@ impl Layout for EquationNode {
}
}
-impl Count for EquationNode {
+impl Count for EquationElem {
fn update(&self) -> Option<CounterUpdate> {
(self.block(StyleChain::default())
&& self.numbering(StyleChain::default()).is_some())
@@ -263,7 +263,7 @@ impl Count for EquationNode {
}
}
-impl LocalName for EquationNode {
+impl LocalName for EquationElem {
fn local_name(&self, lang: Lang) -> &'static str {
match lang {
Lang::GERMAN => "Gleichung",
@@ -276,7 +276,7 @@ pub trait LayoutMath {
fn layout_math(&self, ctx: &mut MathContext) -> SourceResult<()>;
}
-impl LayoutMath for EquationNode {
+impl LayoutMath for EquationElem {
fn layout_math(&self, ctx: &mut MathContext) -> SourceResult<()> {
self.body().layout_math(ctx)
}
@@ -284,45 +284,44 @@ impl LayoutMath for EquationNode {
impl LayoutMath for Content {
fn layout_math(&self, ctx: &mut MathContext) -> SourceResult<()> {
- if let Some(node) = self.to::<SequenceNode>() {
- for child in node.children() {
+ if let Some(children) = self.to_sequence() {
+ for child in children {
child.layout_math(ctx)?;
}
return Ok(());
}
- if let Some(styled) = self.to::<StyledNode>() {
- let map = styled.styles();
- if TextNode::font_in(ctx.styles().chain(&map))
- != TextNode::font_in(ctx.styles())
+ if let Some((elem, styles)) = self.to_styled() {
+ if TextElem::font_in(ctx.styles().chain(&styles))
+ != TextElem::font_in(ctx.styles())
{
let frame = ctx.layout_content(self)?;
ctx.push(FrameFragment::new(ctx, frame).with_spaced(true));
return Ok(());
}
- let prev_map = std::mem::replace(&mut ctx.map, map);
+ let prev_map = std::mem::replace(&mut ctx.local, styles.clone());
let prev_size = ctx.size;
- ctx.map.apply(prev_map.clone());
- ctx.size = TextNode::size_in(ctx.styles());
- styled.body().layout_math(ctx)?;
+ ctx.local.apply(prev_map.clone());
+ ctx.size = TextElem::size_in(ctx.styles());
+ elem.layout_math(ctx)?;
ctx.size = prev_size;
- ctx.map = prev_map;
+ ctx.local = prev_map;
return Ok(());
}
- if self.is::<SpaceNode>() {
+ if self.is::<SpaceElem>() {
ctx.push(MathFragment::Space(ctx.space_width.scaled(ctx)));
return Ok(());
}
- if self.is::<LinebreakNode>() {
+ if self.is::<LinebreakElem>() {
ctx.push(MathFragment::Linebreak);
return Ok(());
}
- if let Some(node) = self.to::<HNode>() {
- if let Spacing::Rel(rel) = node.amount() {
+ if let Some(elem) = self.to::<HElem>() {
+ if let Spacing::Rel(rel) = elem.amount() {
if rel.rel.is_zero() {
ctx.push(MathFragment::Spacing(rel.abs.resolve(ctx.styles())));
}
@@ -330,13 +329,13 @@ impl LayoutMath for Content {
return Ok(());
}
- if let Some(node) = self.to::<TextNode>() {
- ctx.layout_text(node)?;
+ if let Some(elem) = self.to::<TextElem>() {
+ ctx.layout_text(elem)?;
return Ok(());
}
- if let Some(node) = self.with::<dyn LayoutMath>() {
- return node.layout_math(ctx);
+ if let Some(elem) = self.with::<dyn LayoutMath>() {
+ return elem.layout_math(ctx);
}
let mut frame = ctx.layout_content(self)?;
diff --git a/library/src/math/op.rs b/library/src/math/op.rs
index dae43c3a..e8db0c5d 100644
--- a/library/src/math/op.rs
+++ b/library/src/math/op.rs
@@ -20,8 +20,8 @@ use super::*;
///
/// Display: Text Operator
/// Category: math
-#[node(LayoutMath)]
-pub struct OpNode {
+#[element(LayoutMath)]
+pub struct OpElem {
/// The operator's text.
#[required]
pub text: EcoString,
@@ -33,9 +33,9 @@ pub struct OpNode {
pub limits: bool,
}
-impl LayoutMath for OpNode {
+impl LayoutMath for OpElem {
fn layout_math(&self, ctx: &mut MathContext) -> SourceResult<()> {
- let frame = ctx.layout_content(&TextNode::packed(self.text()))?;
+ let frame = ctx.layout_content(&TextElem::packed(self.text()))?;
ctx.push(
FrameFragment::new(ctx, frame)
.with_class(MathClass::Large)
@@ -50,14 +50,14 @@ macro_rules! ops {
pub(super) fn define(math: &mut Scope) {
$(math.define(
stringify!($name),
- OpNode::new(ops!(@name $name $(: $value)?).into())
+ OpElem::new(ops!(@name $name $(: $value)?).into())
.with_limits(ops!(@limit $($tts)*))
.pack()
);)*
let dif = |d| {
- HNode::new(THIN.into()).pack()
- + UprightNode::new(TextNode::packed(d)).pack()
+ HElem::new(THIN.into()).pack()
+ + MathStyleElem::new(TextElem::packed(d)).with_italic(Some(false)).pack()
};
math.define("dif", dif('d'));
math.define("Dif", dif('D'));
diff --git a/library/src/math/root.rs b/library/src/math/root.rs
index b4756b9d..037c6ce7 100644
--- a/library/src/math/root.rs
+++ b/library/src/math/root.rs
@@ -9,17 +9,13 @@ use super::*;
///
/// Display: Square Root
/// Category: math
-#[node(LayoutMath)]
-pub struct SqrtNode {
+/// Returns: content
+#[func]
+pub fn sqrt(
/// The expression to take the square root of.
- #[required]
- pub radicand: Content,
-}
-
-impl LayoutMath for SqrtNode {
- fn layout_math(&self, ctx: &mut MathContext) -> SourceResult<()> {
- layout(ctx, None, &self.radicand(), self.span())
- }
+ radicand: Content,
+) -> Value {
+ RootElem::new(radicand).pack().into()
}
/// A general root.
@@ -31,20 +27,20 @@ impl LayoutMath for SqrtNode {
///
/// Display: Root
/// Category: math
-#[node(LayoutMath)]
-pub struct RootNode {
+#[element(LayoutMath)]
+pub struct RootElem {
/// Which root of the radicand to take.
- #[required]
- index: Content,
+ #[positional]
+ index: Option<Content>,
/// The expression to take the root of.
#[required]
radicand: Content,
}
-impl LayoutMath for RootNode {
+impl LayoutMath for RootElem {
fn layout_math(&self, ctx: &mut MathContext) -> SourceResult<()> {
- layout(ctx, Some(&self.index()), &self.radicand(), self.span())
+ layout(ctx, self.index(ctx.styles()).as_ref(), &self.radicand(), self.span())
}
}
@@ -88,7 +84,7 @@ fn layout(
// Layout the index.
// Script-script style looks too small, we use Script style instead.
ctx.style(ctx.style.with_size(MathSize::Script));
- let index = index.map(|node| ctx.layout_frame(node)).transpose()?;
+ let index = index.map(|elem| ctx.layout_frame(elem)).transpose()?;
ctx.unstyle();
let gap = gap.max((sqrt.height() - radicand.height() - thickness) / 2.0);
@@ -124,9 +120,9 @@ fn layout(
frame.push_frame(sqrt_pos, sqrt);
frame.push(
line_pos,
- Element::Shape(
+ FrameItem::Shape(
Geometry::Line(Point::with_x(radicand.width()))
- .stroked(Stroke { paint: TextNode::fill_in(ctx.styles()), thickness }),
+ .stroked(Stroke { paint: TextElem::fill_in(ctx.styles()), thickness }),
span,
),
);
@@ -139,15 +135,15 @@ fn layout(
/// Select a precomposed radical, if the font has it.
fn precomposed(ctx: &MathContext, index: Option<&Content>, target: Abs) -> Option<Frame> {
- let node = index?.to::<TextNode>()?;
- let c = match node.text().as_str() {
+ let elem = index?.to::<TextElem>()?;
+ let c = match elem.text().as_str() {
"3" => '∛',
"4" => '∜',
_ => return None,
};
ctx.ttf.glyph_index(c)?;
- let glyph = GlyphFragment::new(ctx, c, node.span());
+ let glyph = GlyphFragment::new(ctx, c, elem.span());
let variant = glyph.stretch_vertical(ctx, target, Abs::zero()).frame;
if variant.height() < target {
return None;
diff --git a/library/src/math/row.rs b/library/src/math/row.rs
index ecb2e31e..67d9eeaf 100644
--- a/library/src/math/row.rs
+++ b/library/src/math/row.rs
@@ -1,4 +1,4 @@
-use crate::layout::AlignNode;
+use crate::layout::AlignElem;
use super::*;
@@ -103,7 +103,7 @@ impl MathRow {
pub fn to_frame(self, ctx: &MathContext) -> Frame {
let styles = ctx.styles();
- let align = AlignNode::alignment_in(styles).x.resolve(styles);
+ let align = AlignElem::alignment_in(styles).x.resolve(styles);
self.to_aligned_frame(ctx, &[], align)
}
@@ -124,7 +124,7 @@ impl MathRow {
if self.iter().any(|frag| matches!(frag, MathFragment::Linebreak)) {
let fragments: Vec<_> = std::mem::take(&mut self.0);
let leading = if ctx.style.size >= MathSize::Text {
- ParNode::leading_in(ctx.styles())
+ ParElem::leading_in(ctx.styles())
} else {
TIGHT_LEADING.scaled(ctx)
};
diff --git a/library/src/math/spacing.rs b/library/src/math/spacing.rs
index e1b9d408..848aca78 100644
--- a/library/src/math/spacing.rs
+++ b/library/src/math/spacing.rs
@@ -7,10 +7,10 @@ pub(super) const QUAD: Em = Em::new(1.0);
/// Hook up all spacings.
pub(super) fn define(math: &mut Scope) {
- math.define("thin", HNode::new(THIN.into()).pack());
- math.define("med", HNode::new(MEDIUM.into()).pack());
- math.define("thick", HNode::new(THICK.into()).pack());
- math.define("quad", HNode::new(QUAD.into()).pack());
+ math.define("thin", HElem::new(THIN.into()).pack());
+ math.define("med", HElem::new(MEDIUM.into()).pack());
+ math.define("thick", HElem::new(THICK.into()).pack());
+ math.define("quad", HElem::new(QUAD.into()).pack());
}
/// Create the spacing between two fragments in a given style.
diff --git a/library/src/math/style.rs b/library/src/math/style.rs
index a3383a0c..7a911a0a 100644
--- a/library/src/math/style.rs
+++ b/library/src/math/style.rs
@@ -9,20 +9,13 @@ use super::*;
///
/// Display: Bold
/// Category: math
-#[node(LayoutMath)]
-pub struct BoldNode {
+/// Returns: content
+#[func]
+pub fn bold(
/// The content to style.
- #[required]
- pub body: Content,
-}
-
-impl LayoutMath for BoldNode {
- fn layout_math(&self, ctx: &mut MathContext) -> SourceResult<()> {
- ctx.style(ctx.style.with_bold(true));
- self.body().layout_math(ctx)?;
- ctx.unstyle();
- Ok(())
- }
+ body: Content,
+) -> Value {
+ MathStyleElem::new(body).with_bold(Some(true)).pack().into()
}
/// Upright (non-italic) font style in math.
@@ -34,20 +27,13 @@ impl LayoutMath for BoldNode {
///
/// Display: Upright
/// Category: math
-#[node(LayoutMath)]
-pub struct UprightNode {
+/// Returns: content
+#[func]
+pub fn upright(
/// The content to style.
- #[required]
- pub body: Content,
-}
-
-impl LayoutMath for UprightNode {
- fn layout_math(&self, ctx: &mut MathContext) -> SourceResult<()> {
- ctx.style(ctx.style.with_italic(false));
- self.body().layout_math(ctx)?;
- ctx.unstyle();
- Ok(())
- }
+ body: Content,
+) -> Value {
+ MathStyleElem::new(body).with_italic(Some(false)).pack().into()
}
/// Italic font style in math.
@@ -56,42 +42,30 @@ impl LayoutMath for UprightNode {
///
/// Display: Italic
/// Category: math
-#[node(LayoutMath)]
-pub struct ItalicNode {
+/// Returns: content
+#[func]
+pub fn italic(
/// The content to style.
- #[required]
- pub body: Content,
-}
-
-impl LayoutMath for ItalicNode {
- fn layout_math(&self, ctx: &mut MathContext) -> SourceResult<()> {
- ctx.style(ctx.style.with_italic(true));
- self.body().layout_math(ctx)?;
- ctx.unstyle();
- Ok(())
- }
+ body: Content,
+) -> Value {
+ MathStyleElem::new(body).with_italic(Some(true)).pack().into()
}
-
/// Serif (roman) font style in math.
///
/// This is already the default.
///
/// Display: Serif
/// Category: math
-#[node(LayoutMath)]
-pub struct SerifNode {
+/// Returns: content
+#[func]
+pub fn serif(
/// The content to style.
- #[required]
- pub body: Content,
-}
-
-impl LayoutMath for SerifNode {
- fn layout_math(&self, ctx: &mut MathContext) -> SourceResult<()> {
- ctx.style(ctx.style.with_variant(MathVariant::Serif));
- self.body().layout_math(ctx)?;
- ctx.unstyle();
- Ok(())
- }
+ body: Content,
+) -> Value {
+ MathStyleElem::new(body)
+ .with_variant(Some(MathVariant::Serif))
+ .pack()
+ .into()
}
/// Sans-serif font style in math.
@@ -103,20 +77,16 @@ impl LayoutMath for SerifNode {
///
/// Display: Sans-serif
/// Category: math
-#[node(LayoutMath)]
-pub struct SansNode {
+/// Returns: content
+#[func]
+pub fn sans(
/// The content to style.
- #[required]
- pub body: Content,
-}
-
-impl LayoutMath for SansNode {
- fn layout_math(&self, ctx: &mut MathContext) -> SourceResult<()> {
- ctx.style(ctx.style.with_variant(MathVariant::Sans));
- self.body().layout_math(ctx)?;
- ctx.unstyle();
- Ok(())
- }
+ body: Content,
+) -> Value {
+ MathStyleElem::new(body)
+ .with_variant(Some(MathVariant::Sans))
+ .pack()
+ .into()
}
/// Calligraphic font style in math.
@@ -128,20 +98,16 @@ impl LayoutMath for SansNode {
///
/// Display: Calligraphic
/// Category: math
-#[node(LayoutMath)]
-pub struct CalNode {
+/// Returns: content
+#[func]
+pub fn cal(
/// The content to style.
- #[required]
- pub body: Content,
-}
-
-impl LayoutMath for CalNode {
- fn layout_math(&self, ctx: &mut MathContext) -> SourceResult<()> {
- ctx.style(ctx.style.with_variant(MathVariant::Cal));
- self.body().layout_math(ctx)?;
- ctx.unstyle();
- Ok(())
- }
+ body: Content,
+) -> Value {
+ MathStyleElem::new(body)
+ .with_variant(Some(MathVariant::Cal))
+ .pack()
+ .into()
}
/// Fraktur font style in math.
@@ -153,20 +119,16 @@ impl LayoutMath for CalNode {
///
/// Display: Fraktur
/// Category: math
-#[node(LayoutMath)]
-pub struct FrakNode {
+/// Returns: content
+#[func]
+pub fn frak(
/// The content to style.
- #[required]
- pub body: Content,
-}
-
-impl LayoutMath for FrakNode {
- fn layout_math(&self, ctx: &mut MathContext) -> SourceResult<()> {
- ctx.style(ctx.style.with_variant(MathVariant::Frak));
- self.body().layout_math(ctx)?;
- ctx.unstyle();
- Ok(())
- }
+ body: Content,
+) -> Value {
+ MathStyleElem::new(body)
+ .with_variant(Some(MathVariant::Frak))
+ .pack()
+ .into()
}
/// Monospace font style in math.
@@ -178,20 +140,16 @@ impl LayoutMath for FrakNode {
///
/// Display: Monospace
/// Category: math
-#[node(LayoutMath)]
-pub struct MonoNode {
+/// Returns: content
+#[func]
+pub fn mono(
/// The content to style.
- #[required]
- pub body: Content,
-}
-
-impl LayoutMath for MonoNode {
- fn layout_math(&self, ctx: &mut MathContext) -> SourceResult<()> {
- ctx.style(ctx.style.with_variant(MathVariant::Mono));
- self.body().layout_math(ctx)?;
- ctx.unstyle();
- Ok(())
- }
+ body: Content,
+) -> Value {
+ MathStyleElem::new(body)
+ .with_variant(Some(MathVariant::Mono))
+ .pack()
+ .into()
}
/// Blackboard bold (double-struck) font style in math.
@@ -208,16 +166,51 @@ impl LayoutMath for MonoNode {
///
/// Display: Blackboard Bold
/// Category: math
-#[node(LayoutMath)]
-pub struct BbNode {
+/// Returns: content
+#[func]
+pub fn bb(
+ /// The content to style.
+ body: Content,
+) -> Value {
+ MathStyleElem::new(body)
+ .with_variant(Some(MathVariant::Bb))
+ .pack()
+ .into()
+}
+
+/// A font variant in math.
+///
+/// Display: Bold
+/// Category: math
+#[element(LayoutMath)]
+pub struct MathStyleElem {
/// The content to style.
#[required]
pub body: Content,
+
+ /// The variant to select.
+ pub variant: Option<MathVariant>,
+
+ /// Whether to use bold glyphs.
+ pub bold: Option<bool>,
+
+ /// Whether to use italic glyphs.
+ pub italic: Option<bool>,
}
-impl LayoutMath for BbNode {
+impl LayoutMath for MathStyleElem {
fn layout_math(&self, ctx: &mut MathContext) -> SourceResult<()> {
- ctx.style(ctx.style.with_variant(MathVariant::Bb));
+ let mut style = ctx.style;
+ if let Some(variant) = self.variant(StyleChain::default()) {
+ style = style.with_variant(variant);
+ }
+ if let Some(bold) = self.bold(StyleChain::default()) {
+ style = style.with_bold(bold);
+ }
+ if let Some(italic) = self.italic(StyleChain::default()) {
+ style = style.with_italic(italic);
+ }
+ ctx.style(style);
self.body().layout_math(ctx)?;
ctx.unstyle();
Ok(())
@@ -324,7 +317,7 @@ impl MathSize {
}
/// A mathematical style variant, as defined by Unicode.
-#[derive(Debug, Copy, Clone, Eq, PartialEq)]
+#[derive(Debug, Copy, Clone, Eq, PartialEq, Cast)]
pub enum MathVariant {
Serif,
Sans,
diff --git a/library/src/math/underover.rs b/library/src/math/underover.rs
index cfbb30b6..654da354 100644
--- a/library/src/math/underover.rs
+++ b/library/src/math/underover.rs
@@ -13,14 +13,14 @@ const BRACKET_GAP: Em = Em::new(0.25);
///
/// Display: Underline
/// Category: math
-#[node(LayoutMath)]
-pub struct UnderlineNode {
+#[element(LayoutMath)]
+pub struct UnderlineElem {
/// The content above the line.
#[required]
pub body: Content,
}
-impl LayoutMath for UnderlineNode {
+impl LayoutMath for UnderlineElem {
fn layout_math(&self, ctx: &mut MathContext) -> SourceResult<()> {
layout(ctx, &self.body(), &None, '\u{305}', LINE_GAP, false, self.span())
}
@@ -35,14 +35,14 @@ impl LayoutMath for UnderlineNode {
///
/// Display: Overline
/// Category: math
-#[node(LayoutMath)]
-pub struct OverlineNode {
+#[element(LayoutMath)]
+pub struct OverlineElem {
/// The content below the line.
#[required]
pub body: Content,
}
-impl LayoutMath for OverlineNode {
+impl LayoutMath for OverlineElem {
fn layout_math(&self, ctx: &mut MathContext) -> SourceResult<()> {
layout(ctx, &self.body(), &None, '\u{332}', LINE_GAP, true, self.span())
}
@@ -57,8 +57,8 @@ impl LayoutMath for OverlineNode {
///
/// Display: Underbrace
/// Category: math
-#[node(LayoutMath)]
-pub struct UnderbraceNode {
+#[element(LayoutMath)]
+pub struct UnderbraceElem {
/// The content above the brace.
#[required]
pub body: Content,
@@ -68,7 +68,7 @@ pub struct UnderbraceNode {
pub annotation: Option<Content>,
}
-impl LayoutMath for UnderbraceNode {
+impl LayoutMath for UnderbraceElem {
fn layout_math(&self, ctx: &mut MathContext) -> SourceResult<()> {
layout(
ctx,
@@ -91,8 +91,8 @@ impl LayoutMath for UnderbraceNode {
///
/// Display: Overbrace
/// Category: math
-#[node(LayoutMath)]
-pub struct OverbraceNode {
+#[element(LayoutMath)]
+pub struct OverbraceElem {
/// The content below the brace.
#[required]
pub body: Content,
@@ -102,7 +102,7 @@ pub struct OverbraceNode {
pub annotation: Option<Content>,
}
-impl LayoutMath for OverbraceNode {
+impl LayoutMath for OverbraceElem {
fn layout_math(&self, ctx: &mut MathContext) -> SourceResult<()> {
layout(
ctx,
@@ -125,8 +125,8 @@ impl LayoutMath for OverbraceNode {
///
/// Display: Underbracket
/// Category: math
-#[node(LayoutMath)]
-pub struct UnderbracketNode {
+#[element(LayoutMath)]
+pub struct UnderbracketElem {
/// The content above the bracket.
#[required]
pub body: Content,
@@ -136,7 +136,7 @@ pub struct UnderbracketNode {
pub annotation: Option<Content>,
}
-impl LayoutMath for UnderbracketNode {
+impl LayoutMath for UnderbracketElem {
fn layout_math(&self, ctx: &mut MathContext) -> SourceResult<()> {
layout(
ctx,
@@ -159,8 +159,8 @@ impl LayoutMath for UnderbracketNode {
///
/// Display: Overbracket
/// Category: math
-#[node(LayoutMath)]
-pub struct OverbracketNode {
+#[element(LayoutMath)]
+pub struct OverbracketElem {
/// The content below the bracket.
#[required]
pub body: Content,
@@ -170,7 +170,7 @@ pub struct OverbracketNode {
pub annotation: Option<Content>,
}
-impl LayoutMath for OverbracketNode {
+impl LayoutMath for OverbracketElem {
fn layout_math(&self, ctx: &mut MathContext) -> SourceResult<()> {
layout(
ctx,
diff --git a/library/src/meta/bibliography.rs b/library/src/meta/bibliography.rs
index 64ac1f8e..5f244a8f 100644
--- a/library/src/meta/bibliography.rs
+++ b/library/src/meta/bibliography.rs
@@ -8,18 +8,18 @@ use hayagriva::io::{BibLaTeXError, YamlBibliographyError};
use hayagriva::style::{self, Brackets, Citation, Database, DisplayString, Formatting};
use hayagriva::Entry;
-use super::{LocalName, RefNode};
-use crate::layout::{BlockNode, GridNode, ParNode, Sizing, TrackSizings, VNode};
-use crate::meta::HeadingNode;
+use super::{LocalName, RefElem};
+use crate::layout::{BlockElem, GridElem, ParElem, Sizing, TrackSizings, VElem};
+use crate::meta::HeadingElem;
use crate::prelude::*;
-use crate::text::TextNode;
+use crate::text::TextElem;
/// A bibliography / reference listing.
///
/// Display: Bibliography
/// Category: meta
-#[node(Locatable, Synthesize, Show, LocalName)]
-pub struct BibliographyNode {
+#[element(Locatable, Synthesize, Show, LocalName)]
+pub struct BibliographyElem {
/// Path to a Hayagriva `.yml` or BibLaTeX `.bib` file.
#[required]
#[parse(
@@ -45,11 +45,11 @@ pub struct BibliographyNode {
pub style: BibliographyStyle,
}
-impl BibliographyNode {
+impl BibliographyElem {
/// Find the document's bibliography.
pub fn find(introspector: Tracked<Introspector>) -> StrResult<Self> {
- let mut iter = introspector.query(Selector::node::<Self>()).into_iter();
- let Some(node) = iter.next() else {
+ let mut iter = introspector.query(Self::func().select()).into_iter();
+ let Some(elem) = iter.next() else {
return Err("the document does not contain a bibliography".into());
};
@@ -57,15 +57,15 @@ impl BibliographyNode {
Err("multiple bibliographies are not supported")?;
}
- Ok(node.to::<Self>().unwrap().clone())
+ Ok(elem.to::<Self>().unwrap().clone())
}
/// Whether the bibliography contains the given key.
pub fn has(vt: &Vt, key: &str) -> bool {
vt.introspector
- .query(Selector::node::<Self>())
+ .query(Self::func().select())
.into_iter()
- .flat_map(|node| load(vt.world, &node.to::<Self>().unwrap().path()))
+ .flat_map(|elem| load(vt.world, &elem.to::<Self>().unwrap().path()))
.flatten()
.any(|entry| entry.key() == key)
}
@@ -76,7 +76,7 @@ impl BibliographyNode {
introspector: Tracked<Introspector>,
) -> Vec<(EcoString, Option<EcoString>)> {
Self::find(introspector)
- .and_then(|node| load(world, &node.path()))
+ .and_then(|elem| load(world, &elem.path()))
.into_iter()
.flatten()
.map(|entry| {
@@ -89,13 +89,13 @@ impl BibliographyNode {
}
}
-impl Synthesize for BibliographyNode {
+impl Synthesize for BibliographyElem {
fn synthesize(&mut self, _: &Vt, styles: StyleChain) {
self.push_style(self.style(styles));
}
}
-impl Show for BibliographyNode {
+impl Show for BibliographyElem {
fn show(&self, vt: &mut Vt, styles: StyleChain) -> SourceResult<Content> {
const COLUMN_GUTTER: Em = Em::new(0.65);
const INDENT: Em = Em::new(1.5);
@@ -103,12 +103,12 @@ impl Show for BibliographyNode {
let mut seq = vec![];
if let Some(title) = self.title(styles) {
let title = title.clone().unwrap_or_else(|| {
- TextNode::packed(self.local_name(TextNode::lang_in(styles)))
+ TextElem::packed(self.local_name(TextElem::lang_in(styles)))
.spanned(self.span())
});
seq.push(
- HeadingNode::new(title)
+ HeadingElem::new(title)
.with_level(NonZeroUsize::ONE)
.with_numbering(None)
.pack(),
@@ -121,7 +121,7 @@ impl Show for BibliographyNode {
let works = Works::new(vt).at(self.span())?;
- let row_gutter = BlockNode::below_in(styles).amount();
+ let row_gutter = BlockElem::below_in(styles).amount();
if works.references.iter().any(|(prefix, _)| prefix.is_some()) {
let mut cells = vec![];
for (prefix, reference) in &works.references {
@@ -129,9 +129,9 @@ impl Show for BibliographyNode {
cells.push(reference.clone());
}
- seq.push(VNode::new(row_gutter).with_weakness(3).pack());
+ seq.push(VElem::new(row_gutter).with_weakness(3).pack());
seq.push(
- GridNode::new(cells)
+ GridElem::new(cells)
.with_columns(TrackSizings(vec![Sizing::Auto; 2]))
.with_column_gutter(TrackSizings(vec![COLUMN_GUTTER.into()]))
.with_row_gutter(TrackSizings(vec![row_gutter.into()]))
@@ -140,13 +140,13 @@ impl Show for BibliographyNode {
} else {
let mut entries = vec![];
for (_, reference) in &works.references {
- entries.push(VNode::new(row_gutter).with_weakness(3).pack());
+ entries.push(VElem::new(row_gutter).with_weakness(3).pack());
entries.push(reference.clone());
}
seq.push(
Content::sequence(entries)
- .styled(ParNode::set_hanging_indent(INDENT.into())),
+ .styled(ParElem::set_hanging_indent(INDENT.into())),
);
}
@@ -154,7 +154,7 @@ impl Show for BibliographyNode {
}
}
-impl LocalName for BibliographyNode {
+impl LocalName for BibliographyElem {
fn local_name(&self, lang: Lang) -> &'static str {
match lang {
Lang::GERMAN => "Bibliographie",
@@ -196,8 +196,8 @@ impl BibliographyStyle {
///
/// Display: Citation
/// Category: meta
-#[node(Locatable, Synthesize, Show)]
-pub struct CiteNode {
+#[element(Locatable, Synthesize, Show)]
+pub struct CiteElem {
/// The citation key.
#[variadic]
pub keys: Vec<EcoString>,
@@ -217,7 +217,7 @@ pub struct CiteNode {
pub style: Smart<CitationStyle>,
}
-impl Synthesize for CiteNode {
+impl Synthesize for CiteElem {
fn synthesize(&mut self, _: &Vt, styles: StyleChain) {
self.push_supplement(self.supplement(styles));
self.push_brackets(self.brackets(styles));
@@ -225,17 +225,17 @@ impl Synthesize for CiteNode {
}
}
-impl Show for CiteNode {
+impl Show for CiteElem {
fn show(&self, vt: &mut Vt, _: StyleChain) -> SourceResult<Content> {
if !vt.introspector.init() {
return Ok(Content::empty());
}
let works = Works::new(vt).at(self.span())?;
- let id = self.0.stable_id().unwrap();
+ let location = self.0.location().unwrap();
works
.citations
- .get(&id)
+ .get(&location)
.cloned()
.flatten()
.ok_or("bibliography does not contain this key")
@@ -264,24 +264,24 @@ pub enum CitationStyle {
/// Fully formatted citations and references.
#[derive(Default)]
struct Works {
- citations: HashMap<StableId, Option<Content>>,
+ citations: HashMap<Location, Option<Content>>,
references: Vec<(Option<Content>, Content)>,
}
impl Works {
/// Prepare all things need to cite a work or format a bibliography.
fn new(vt: &Vt) -> StrResult<Arc<Self>> {
- let bibliography = BibliographyNode::find(vt.introspector)?;
+ let bibliography = BibliographyElem::find(vt.introspector)?;
let citations = vt
.introspector
.query(Selector::Any(eco_vec![
- Selector::node::<RefNode>(),
- Selector::node::<CiteNode>(),
+ RefElem::func().select(),
+ CiteElem::func().select(),
]))
.into_iter()
- .map(|node| match node.to::<RefNode>() {
+ .map(|elem| match elem.to::<RefElem>() {
Some(reference) => reference.to_citation(StyleChain::default()),
- _ => node.to::<CiteNode>().unwrap().clone(),
+ _ => elem.to::<CiteElem>().unwrap().clone(),
})
.collect();
Ok(create(vt.world, bibliography, citations))
@@ -292,19 +292,19 @@ impl Works {
#[comemo::memoize]
fn create(
world: Tracked<dyn World>,
- bibliography: BibliographyNode,
- citations: Vec<CiteNode>,
+ bibliography: BibliographyElem,
+ citations: Vec<CiteElem>,
) -> Arc<Works> {
let span = bibliography.span();
let entries = load(world, &bibliography.path()).unwrap();
let style = bibliography.style(StyleChain::default());
- let bib_id = bibliography.0.stable_id().unwrap();
- let ref_id = |target: &Entry| {
+ let bib_location = bibliography.0.location().unwrap();
+ let ref_location = |target: &Entry| {
let i = entries
.iter()
.position(|entry| entry.key() == target.key())
.unwrap_or_default();
- bib_id.variant(i)
+ bib_location.variant(i)
};
let mut db = Database::new();
@@ -312,7 +312,7 @@ fn create(
let mut preliminary = vec![];
for citation in citations {
- let cite_id = citation.0.stable_id().unwrap();
+ let cite_id = citation.0.location().unwrap();
let entries = citation
.keys()
.into_iter()
@@ -333,8 +333,8 @@ fn create(
let citations = preliminary
.into_iter()
.map(|(citation, cited)| {
- let id = citation.0.stable_id().unwrap();
- let Some(cited) = cited else { return (id, None) };
+ let location = citation.0.location().unwrap();
+ let Some(cited) = cited else { return (location, None) };
let mut supplement = citation.supplement(StyleChain::default());
let brackets = citation.brackets(StyleChain::default());
@@ -376,27 +376,27 @@ fn create(
}
if i > 0 {
- content += TextNode::packed(",\u{a0}");
+ content += TextElem::packed(",\u{a0}");
}
// Format and link to the reference entry.
content += format_display_string(&display, supplement, citation.span())
- .linked(Link::Node(ref_id(entry)));
+ .linked(Destination::Location(ref_location(entry)));
}
if brackets && len > 1 {
content = match citation_style.brackets() {
Brackets::None => content,
Brackets::Round => {
- TextNode::packed('(') + content + TextNode::packed(')')
+ TextElem::packed('(') + content + TextElem::packed(')')
}
Brackets::Square => {
- TextNode::packed('[') + content + TextNode::packed(']')
+ TextElem::packed('[') + content + TextElem::packed(']')
}
};
}
- (id, Some(content))
+ (location, Some(content))
})
.collect();
@@ -414,15 +414,15 @@ fn create(
// Make link from citation to here work.
let backlink = {
let mut content = Content::empty();
- content.set_stable_id(ref_id(&reference.entry));
- MetaNode::set_data(vec![Meta::Node(content)])
+ content.set_location(ref_location(&reference.entry));
+ MetaElem::set_data(vec![Meta::Elem(content)])
};
let prefix = reference.prefix.map(|prefix| {
// Format and link to first citation.
let bracketed = prefix.with_default_brackets(&*citation_style);
format_display_string(&bracketed, None, span)
- .linked(Link::Node(ids[reference.entry.key()]))
+ .linked(Destination::Location(ids[reference.entry.key()]))
.styled(backlink.clone())
});
@@ -510,7 +510,7 @@ fn format_display_string(
let mut content = if segment == SUPPLEMENT && supplement.is_some() {
supplement.take().unwrap_or_default()
} else {
- TextNode::packed(segment).spanned(span)
+ TextElem::packed(segment).spanned(span)
};
for (range, fmt) in &string.formatting {
@@ -522,7 +522,7 @@ fn format_display_string(
Formatting::Bold => content.strong(),
Formatting::Italic => content.emph(),
Formatting::Link(link) => {
- content.linked(Link::Dest(Destination::Url(link.as_str().into())))
+ content.linked(Destination::Url(link.as_str().into()))
}
};
}
diff --git a/library/src/meta/context.rs b/library/src/meta/context.rs
index 9e542847..dbb84812 100644
--- a/library/src/meta/context.rs
+++ b/library/src/meta/context.rs
@@ -10,28 +10,28 @@ pub fn locate(
/// The function to call with the location.
func: Func,
) -> Value {
- LocateNode::new(func).pack().into()
+ LocateElem::new(func).pack().into()
}
/// Executes a `locate` call.
///
/// Display: Styled
/// Category: special
-#[node(Locatable, Show)]
-struct LocateNode {
+#[element(Locatable, Show)]
+struct LocateElem {
/// The function to call with the location.
#[required]
func: Func,
}
-impl Show for LocateNode {
+impl Show for LocateElem {
fn show(&self, vt: &mut Vt, _: StyleChain) -> SourceResult<Content> {
if !vt.introspector.init() {
return Ok(Content::empty());
}
- let id = self.0.stable_id().unwrap();
- Ok(self.func().call_vt(vt, [id.into()])?.display())
+ let location = self.0.location().unwrap();
+ Ok(self.func().call_vt(vt, [location.into()])?.display())
}
}
@@ -45,21 +45,21 @@ pub fn style(
/// The function to call with the styles.
func: Func,
) -> Value {
- StyleNode::new(func).pack().into()
+ StyleElem::new(func).pack().into()
}
/// Executes a style access.
///
/// Display: Style
/// Category: special
-#[node(Show)]
-struct StyleNode {
+#[element(Show)]
+struct StyleElem {
/// The function to call with the styles.
#[required]
func: Func,
}
-impl Show for StyleNode {
+impl Show for StyleElem {
fn show(&self, vt: &mut Vt, styles: StyleChain) -> SourceResult<Content> {
Ok(self.func().call_vt(vt, [styles.to_map().into()])?.display())
}
diff --git a/library/src/meta/counter.rs b/library/src/meta/counter.rs
index f033a04f..3cfc2cd5 100644
--- a/library/src/meta/counter.rs
+++ b/library/src/meta/counter.rs
@@ -6,7 +6,7 @@ use smallvec::{smallvec, SmallVec};
use typst::eval::Tracer;
use super::{Numbering, NumberingPattern};
-use crate::layout::PageNode;
+use crate::layout::PageElem;
use crate::prelude::*;
/// Count through pages, elements, and more.
@@ -32,9 +32,9 @@ impl Counter {
Self(key)
}
- /// The counter for the given node.
- pub fn of(id: NodeId) -> Self {
- Self::new(CounterKey::Selector(Selector::Node(id, None)))
+ /// The counter for the given element.
+ pub fn of(func: ElemFunc) -> Self {
+ Self::new(CounterKey::Selector(Selector::Elem(func, None)))
}
/// Call a method on counter.
@@ -69,23 +69,23 @@ impl Counter {
/// Display the current value of the counter.
pub fn display(self, numbering: Numbering, both: bool) -> Content {
- DisplayNode::new(self, numbering, both).pack()
+ DisplayElem::new(self, numbering, both).pack()
}
/// Get the value of the state at the given location.
- pub fn at(&self, vt: &mut Vt, id: StableId) -> SourceResult<CounterState> {
+ pub fn at(&self, vt: &mut Vt, location: Location) -> SourceResult<CounterState> {
let sequence = self.sequence(vt)?;
- let offset = vt.introspector.query_before(self.selector(), id).len();
+ let offset = vt.introspector.query_before(self.selector(), location).len();
let (mut state, page) = sequence[offset].clone();
if self.is_page() {
- let delta = vt.introspector.page(id).get() - page.get();
+ let delta = vt.introspector.page(location).get() - page.get();
state.step(NonZeroUsize::ONE, delta);
}
Ok(state)
}
/// Get the value of the state at the final location.
- pub fn final_(&self, vt: &mut Vt, _: StableId) -> SourceResult<CounterState> {
+ pub fn final_(&self, vt: &mut Vt, _: Location) -> SourceResult<CounterState> {
let sequence = self.sequence(vt)?;
let (mut state, page) = sequence.last().unwrap().clone();
if self.is_page() {
@@ -96,13 +96,13 @@ impl Counter {
}
/// Get the current and final value of the state combined in one state.
- pub fn both(&self, vt: &mut Vt, id: StableId) -> SourceResult<CounterState> {
+ pub fn both(&self, vt: &mut Vt, location: Location) -> SourceResult<CounterState> {
let sequence = self.sequence(vt)?;
- let offset = vt.introspector.query_before(self.selector(), id).len();
+ let offset = vt.introspector.query_before(self.selector(), location).len();
let (mut at_state, at_page) = sequence[offset].clone();
let (mut final_state, final_page) = sequence.last().unwrap().clone();
if self.is_page() {
- let at_delta = vt.introspector.page(id).get() - at_page.get();
+ let at_delta = vt.introspector.page(location).get() - at_page.get();
at_state.step(NonZeroUsize::ONE, at_delta);
let final_delta = vt.introspector.pages().get() - final_page.get();
final_state.step(NonZeroUsize::ONE, final_delta);
@@ -112,7 +112,7 @@ impl Counter {
/// Produce content that performs a state update.
pub fn update(self, update: CounterUpdate) -> Content {
- UpdateNode::new(self, update).pack()
+ UpdateElem::new(self, update).pack()
}
/// Produce the whole sequence of counter states.
@@ -148,11 +148,11 @@ impl Counter {
let mut page = NonZeroUsize::ONE;
let mut stops = eco_vec![(state.clone(), page)];
- for node in introspector.query(self.selector()) {
+ for elem in introspector.query(self.selector()) {
if self.is_page() {
- let id = node.stable_id().unwrap();
+ let location = elem.location().unwrap();
let prev = page;
- page = introspector.page(id);
+ page = introspector.page(location);
let delta = page.get() - prev.get();
if delta > 0 {
@@ -160,9 +160,9 @@ impl Counter {
}
}
- if let Some(update) = match node.to::<UpdateNode>() {
- Some(node) => Some(node.update()),
- None => match node.with::<dyn Count>() {
+ if let Some(update) = match elem.to::<UpdateElem>() {
+ Some(elem) => Some(elem.update()),
+ None => match elem.with::<dyn Count>() {
Some(countable) => countable.update(),
None => Some(CounterUpdate::Step(NonZeroUsize::ONE)),
},
@@ -178,10 +178,8 @@ impl Counter {
/// The selector relevant for this counter's updates.
fn selector(&self) -> Selector {
- let mut selector = Selector::Node(
- NodeId::of::<UpdateNode>(),
- Some(dict! { "counter" => self.clone() }),
- );
+ let mut selector =
+ Selector::Elem(UpdateElem::func(), Some(dict! { "counter" => self.clone() }));
if let CounterKey::Selector(key) = &self.0 {
selector = Selector::Any(eco_vec![selector, key.clone()]);
@@ -224,20 +222,16 @@ cast_from_value! {
CounterKey,
v: Str => Self::Str(v),
label: Label => Self::Selector(Selector::Label(label)),
- func: Func => {
- let Some(id) = func.id() else {
- return Err("this function is not selectable".into());
- };
-
- if id == NodeId::of::<PageNode>() {
+ element: ElemFunc => {
+ if element == PageElem::func() {
return Ok(Self::Page);
}
- if !Content::new(id).can::<dyn Locatable>() {
- Err(eco_format!("cannot count through {}s", id.name))?;
+ if !Content::new(element).can::<dyn Locatable>() {
+ Err(eco_format!("cannot count through {}s", element.name()))?;
}
- Self::Selector(Selector::Node(id, None))
+ Self::Selector(Selector::Elem(element, None))
}
}
@@ -274,9 +268,9 @@ cast_from_value! {
v: Func => Self::Func(v),
}
-/// Nodes that have special counting behaviour.
+/// Elements that have special counting behaviour.
pub trait Count {
- /// Get the counter update for this node.
+ /// Get the counter update for this element.
fn update(&self) -> Option<CounterUpdate>;
}
@@ -342,8 +336,8 @@ cast_to_value! {
///
/// Display: State
/// Category: special
-#[node(Locatable, Show)]
-struct DisplayNode {
+#[element(Locatable, Show)]
+struct DisplayElem {
/// The counter.
#[required]
counter: Counter,
@@ -357,12 +351,16 @@ struct DisplayNode {
both: bool,
}
-impl Show for DisplayNode {
+impl Show for DisplayElem {
fn show(&self, vt: &mut Vt, _: StyleChain) -> SourceResult<Content> {
- let id = self.0.stable_id().unwrap();
+ let location = self.0.location().unwrap();
let counter = self.counter();
let numbering = self.numbering();
- let state = if self.both() { counter.both(vt, id) } else { counter.at(vt, id) }?;
+ let state = if self.both() {
+ counter.both(vt, location)?
+ } else {
+ counter.at(vt, location)?
+ };
state.display(vt, &numbering)
}
}
@@ -371,8 +369,8 @@ impl Show for DisplayNode {
///
/// Display: State
/// Category: special
-#[node(Locatable, Show)]
-struct UpdateNode {
+#[element(Locatable, Show)]
+struct UpdateElem {
/// The counter.
#[required]
counter: Counter,
@@ -382,7 +380,7 @@ struct UpdateNode {
update: CounterUpdate,
}
-impl Show for UpdateNode {
+impl Show for UpdateElem {
fn show(&self, _: &mut Vt, _: StyleChain) -> SourceResult<Content> {
Ok(Content::empty())
}
diff --git a/library/src/meta/document.rs b/library/src/meta/document.rs
index 75e78184..99e5c6b6 100644
--- a/library/src/meta/document.rs
+++ b/library/src/meta/document.rs
@@ -1,6 +1,4 @@
-use typst::model::StyledNode;
-
-use crate::layout::{LayoutRoot, PageNode};
+use crate::layout::{LayoutRoot, PageElem};
use crate::prelude::*;
/// The root element of a document and its metadata.
@@ -14,8 +12,8 @@ use crate::prelude::*;
///
/// Display: Document
/// Category: meta
-#[node(LayoutRoot)]
-pub struct DocumentNode {
+#[element(LayoutRoot)]
+pub struct DocumentElem {
/// The document's title. This is often rendered as the title of the
/// PDF viewer window.
pub title: Option<EcoString>,
@@ -29,22 +27,20 @@ pub struct DocumentNode {
pub children: Vec<Content>,
}
-impl LayoutRoot for DocumentNode {
+impl LayoutRoot for DocumentElem {
/// Layout the document into a sequence of frames, one per page.
fn layout_root(&self, vt: &mut Vt, styles: StyleChain) -> SourceResult<Document> {
let mut pages = vec![];
- for mut child in self.children() {
- let map;
+ for mut child in &self.children() {
let outer = styles;
- let mut styles = outer;
- if let Some(node) = child.to::<StyledNode>() {
- map = node.styles();
- styles = outer.chain(&map);
- child = node.body();
+ let mut styles = styles;
+ if let Some((elem, local)) = child.to_styled() {
+ styles = outer.chain(local);
+ child = elem;
}
- if let Some(page) = child.to::<PageNode>() {
+ if let Some(page) = child.to::<PageElem>() {
let fragment = page.layout(vt, styles)?;
pages.extend(fragment);
} else {
diff --git a/library/src/meta/figure.rs b/library/src/meta/figure.rs
index 6f9011b8..9251f3ef 100644
--- a/library/src/meta/figure.rs
+++ b/library/src/meta/figure.rs
@@ -1,9 +1,9 @@
use std::str::FromStr;
use super::{Count, Counter, CounterUpdate, LocalName, Numbering, NumberingPattern};
-use crate::layout::{BlockNode, VNode};
+use crate::layout::{BlockElem, VElem};
use crate::prelude::*;
-use crate::text::TextNode;
+use crate::text::TextElem;
/// A figure with an optional caption.
///
@@ -23,8 +23,8 @@ use crate::text::TextNode;
///
/// Display: Figure
/// Category: meta
-#[node(Locatable, Synthesize, Count, Show, LocalName)]
-pub struct FigureNode {
+#[element(Locatable, Synthesize, Count, Show, LocalName)]
+pub struct FigureElem {
/// The content of the figure. Often, an [image]($func/image).
#[required]
pub body: Content,
@@ -42,32 +42,32 @@ pub struct FigureNode {
pub gap: Length,
}
-impl Synthesize for FigureNode {
+impl Synthesize for FigureElem {
fn synthesize(&mut self, _: &Vt, styles: StyleChain) {
self.push_numbering(self.numbering(styles));
}
}
-impl Show for FigureNode {
+impl Show for FigureElem {
fn show(&self, _: &mut Vt, styles: StyleChain) -> SourceResult<Content> {
let mut realized = self.body();
if let Some(mut caption) = self.caption(styles) {
if let Some(numbering) = self.numbering(styles) {
- let name = self.local_name(TextNode::lang_in(styles));
- caption = TextNode::packed(eco_format!("{name}\u{a0}"))
- + Counter::of(Self::id())
+ let name = self.local_name(TextElem::lang_in(styles));
+ caption = TextElem::packed(eco_format!("{name}\u{a0}"))
+ + Counter::of(Self::func())
.display(numbering, false)
.spanned(self.span())
- + TextNode::packed(": ")
+ + TextElem::packed(": ")
+ caption;
}
- realized += VNode::weak(self.gap(styles).into()).pack();
+ realized += VElem::weak(self.gap(styles).into()).pack();
realized += caption;
}
- Ok(BlockNode::new()
+ Ok(BlockElem::new()
.with_body(Some(realized))
.with_breakable(false)
.pack()
@@ -75,7 +75,7 @@ impl Show for FigureNode {
}
}
-impl Count for FigureNode {
+impl Count for FigureElem {
fn update(&self) -> Option<CounterUpdate> {
self.numbering(StyleChain::default())
.is_some()
@@ -83,7 +83,7 @@ impl Count for FigureNode {
}
}
-impl LocalName for FigureNode {
+impl LocalName for FigureElem {
fn local_name(&self, lang: Lang) -> &'static str {
match lang {
Lang::GERMAN => "Abbildung",
diff --git a/library/src/meta/heading.rs b/library/src/meta/heading.rs
index 61605e67..1eaca187 100644
--- a/library/src/meta/heading.rs
+++ b/library/src/meta/heading.rs
@@ -1,10 +1,10 @@
use typst::font::FontWeight;
use super::{Counter, CounterUpdate, LocalName, Numbering};
-use crate::layout::{BlockNode, HNode, VNode};
+use crate::layout::{BlockElem, HElem, VElem};
use crate::meta::Count;
use crate::prelude::*;
-use crate::text::{TextNode, TextSize};
+use crate::text::{TextElem, TextSize};
/// A section heading.
///
@@ -41,8 +41,8 @@ use crate::text::{TextNode, TextSize};
///
/// Display: Heading
/// Category: meta
-#[node(Locatable, Synthesize, Count, Show, Finalize, LocalName)]
-pub struct HeadingNode {
+#[element(Locatable, Synthesize, Count, Show, Finalize, LocalName)]
+pub struct HeadingElem {
/// The logical nesting depth of the heading, starting from one.
#[default(NonZeroUsize::ONE)]
pub level: NonZeroUsize,
@@ -79,7 +79,7 @@ pub struct HeadingNode {
pub body: Content,
}
-impl Synthesize for HeadingNode {
+impl Synthesize for HeadingElem {
fn synthesize(&mut self, _: &Vt, styles: StyleChain) {
self.push_level(self.level(styles));
self.push_numbering(self.numbering(styles));
@@ -87,20 +87,21 @@ impl Synthesize for HeadingNode {
}
}
-impl Show for HeadingNode {
+impl Show for HeadingElem {
fn show(&self, _: &mut Vt, styles: StyleChain) -> SourceResult<Content> {
let mut realized = self.body();
if let Some(numbering) = self.numbering(styles) {
- realized =
- Counter::of(Self::id()).display(numbering, false).spanned(self.span())
- + HNode::new(Em::new(0.3).into()).with_weak(true).pack()
- + realized;
+ realized = Counter::of(Self::func())
+ .display(numbering, false)
+ .spanned(self.span())
+ + HElem::new(Em::new(0.3).into()).with_weak(true).pack()
+ + realized;
}
- Ok(BlockNode::new().with_body(Some(realized)).pack())
+ Ok(BlockElem::new().with_body(Some(realized)).pack())
}
}
-impl Finalize for HeadingNode {
+impl Finalize for HeadingElem {
fn finalize(&self, realized: Content, styles: StyleChain) -> Content {
let level = self.level(styles).get();
let scale = match level {
@@ -113,17 +114,17 @@ impl Finalize for HeadingNode {
let above = Em::new(if level == 1 { 1.8 } else { 1.44 }) / scale;
let below = Em::new(0.75) / scale;
- let mut map = StyleMap::new();
- map.set(TextNode::set_size(TextSize(size.into())));
- map.set(TextNode::set_weight(FontWeight::BOLD));
- map.set(BlockNode::set_above(VNode::block_around(above.into())));
- map.set(BlockNode::set_below(VNode::block_around(below.into())));
- map.set(BlockNode::set_sticky(true));
- realized.styled_with_map(map)
+ let mut styles = Styles::new();
+ styles.set(TextElem::set_size(TextSize(size.into())));
+ styles.set(TextElem::set_weight(FontWeight::BOLD));
+ styles.set(BlockElem::set_above(VElem::block_around(above.into())));
+ styles.set(BlockElem::set_below(VElem::block_around(below.into())));
+ styles.set(BlockElem::set_sticky(true));
+ realized.styled_with_map(styles)
}
}
-impl Count for HeadingNode {
+impl Count for HeadingElem {
fn update(&self) -> Option<CounterUpdate> {
self.numbering(StyleChain::default())
.is_some()
@@ -132,11 +133,11 @@ impl Count for HeadingNode {
}
cast_from_value! {
- HeadingNode,
+ HeadingElem,
v: Content => v.to::<Self>().ok_or("expected heading")?.clone(),
}
-impl LocalName for HeadingNode {
+impl LocalName for HeadingElem {
fn local_name(&self, lang: Lang) -> &'static str {
match lang {
Lang::GERMAN => "Abschnitt",
diff --git a/library/src/meta/link.rs b/library/src/meta/link.rs
index e9b8bcc6..c82a7443 100644
--- a/library/src/meta/link.rs
+++ b/library/src/meta/link.rs
@@ -1,5 +1,5 @@
use crate::prelude::*;
-use crate::text::{Hyphenate, TextNode};
+use crate::text::{Hyphenate, TextElem};
/// Link to a URL or another location in the document.
///
@@ -25,19 +25,20 @@ use crate::text::{Hyphenate, TextNode};
///
/// Display: Link
/// Category: meta
-#[node(Show, Finalize)]
-pub struct LinkNode {
+#[element(Show, Finalize)]
+pub struct LinkElem {
/// The destination the link points to.
///
- /// - To link to web pages, `dest` should be a valid URL string. If the URL is
- /// in the `mailto:` or `tel:` scheme and the `body` parameter is omitted,
- /// the email address or phone number will be the link's body, without the
- /// scheme.
+ /// - To link to web pages, `dest` should be a valid URL string. If the URL
+ /// is in the `mailto:` or `tel:` scheme and the `body` parameter is
+ /// omitted, the email address or phone number will be the link's body,
+ /// without the scheme.
///
- /// - To link to another part of the document, `dest` must contain a
- /// dictionary with a `page` key of type `integer` and `x` and `y`
- /// coordinates of type `length`. Pages are counted from one, and the
- /// coordinates are relative to the page's top left corner.
+ /// - To link to another part of the document, `dest` can take one of two
+ /// forms: A [`location`]($func/locate) or a dictionary with a `page` key
+ /// of type `integer` and `x` and `y` coordinates of type `length`. Pages
+ /// are counted from one, and the coordinates are relative to the page's
+ /// top left corner.
///
/// ```example
/// #link("mailto:hello@typst.app") \
@@ -45,7 +46,6 @@ pub struct LinkNode {
/// Go to top
/// ]
/// ```
- ///
#[required]
#[parse(
let dest = args.expect::<Destination>("destination")?;
@@ -64,30 +64,30 @@ pub struct LinkNode {
Some(body) => body,
None => body_from_url(url),
},
- Destination::Internal(_) => args.expect("body")?,
+ _ => args.expect("body")?,
})]
pub body: Content,
}
-impl LinkNode {
- /// Create a link node from a URL with its bare text.
+impl LinkElem {
+ /// Create a link element from a URL with its bare text.
pub fn from_url(url: EcoString) -> Self {
let body = body_from_url(&url);
Self::new(Destination::Url(url), body)
}
}
-impl Show for LinkNode {
+impl Show for LinkElem {
fn show(&self, _: &mut Vt, _: StyleChain) -> SourceResult<Content> {
Ok(self.body())
}
}
-impl Finalize for LinkNode {
+impl Finalize for LinkElem {
fn finalize(&self, realized: Content, _: StyleChain) -> Content {
realized
- .linked(Link::Dest(self.dest()))
- .styled(TextNode::set_hyphenate(Hyphenate(Smart::Custom(false))))
+ .linked(self.dest())
+ .styled(TextElem::set_hyphenate(Hyphenate(Smart::Custom(false))))
}
}
@@ -97,5 +97,5 @@ fn body_from_url(url: &EcoString) -> Content {
text = text.trim_start_matches(prefix);
}
let shorter = text.len() < url.len();
- TextNode::packed(if shorter { text.into() } else { url.clone() })
+ TextElem::packed(if shorter { text.into() } else { url.clone() })
}
diff --git a/library/src/meta/outline.rs b/library/src/meta/outline.rs
index a0a23897..002d757e 100644
--- a/library/src/meta/outline.rs
+++ b/library/src/meta/outline.rs
@@ -1,7 +1,7 @@
-use super::{Counter, HeadingNode, LocalName};
-use crate::layout::{BoxNode, HNode, HideNode, ParbreakNode, RepeatNode};
+use super::{Counter, HeadingElem, LocalName};
+use crate::layout::{BoxElem, HElem, HideElem, ParbreakElem, RepeatElem};
use crate::prelude::*;
-use crate::text::{LinebreakNode, SpaceNode, TextNode};
+use crate::text::{LinebreakElem, SpaceElem, TextElem};
/// A section outline / table of contents.
///
@@ -22,8 +22,8 @@ use crate::text::{LinebreakNode, SpaceNode, TextNode};
///
/// Display: Outline
/// Category: meta
-#[node(Show, LocalName)]
-pub struct OutlineNode {
+#[element(Show, LocalName)]
+pub struct OutlineElem {
/// The title of the outline.
///
/// - When set to `{auto}`, an appropriate title for the [text
@@ -65,21 +65,21 @@ pub struct OutlineNode {
///
/// = A New Beginning
/// ```
- #[default(Some(RepeatNode::new(TextNode::packed(".")).pack()))]
+ #[default(Some(RepeatElem::new(TextElem::packed(".")).pack()))]
pub fill: Option<Content>,
}
-impl Show for OutlineNode {
+impl Show for OutlineElem {
fn show(&self, vt: &mut Vt, styles: StyleChain) -> SourceResult<Content> {
- let mut seq = vec![ParbreakNode::new().pack()];
+ let mut seq = vec![ParbreakElem::new().pack()];
if let Some(title) = self.title(styles) {
let title = title.clone().unwrap_or_else(|| {
- TextNode::packed(self.local_name(TextNode::lang_in(styles)))
+ TextElem::packed(self.local_name(TextElem::lang_in(styles)))
.spanned(self.span())
});
seq.push(
- HeadingNode::new(title)
+ HeadingElem::new(title)
.with_level(NonZeroUsize::ONE)
.with_numbering(None)
.with_outlined(false)
@@ -90,15 +90,15 @@ impl Show for OutlineNode {
let indent = self.indent(styles);
let depth = self.depth(styles);
- let mut ancestors: Vec<&HeadingNode> = vec![];
- let nodes = vt.introspector.query(Selector::Node(
- NodeId::of::<HeadingNode>(),
+ let mut ancestors: Vec<&HeadingElem> = vec![];
+ let elems = vt.introspector.query(Selector::Elem(
+ HeadingElem::func(),
Some(dict! { "outlined" => true }),
));
- for node in &nodes {
- let heading = node.to::<HeadingNode>().unwrap();
- let stable_id = heading.0.stable_id().unwrap();
+ for elem in &elems {
+ let heading = elem.to::<HeadingElem>().unwrap();
+ let location = heading.0.location().unwrap();
if !heading.outlined(StyleChain::default()) {
continue;
}
@@ -120,60 +120,60 @@ impl Show for OutlineNode {
let mut hidden = Content::empty();
for ancestor in &ancestors {
if let Some(numbering) = ancestor.numbering(StyleChain::default()) {
- let numbers = Counter::of(HeadingNode::id())
- .at(vt, ancestor.0.stable_id().unwrap())?
+ let numbers = Counter::of(HeadingElem::func())
+ .at(vt, ancestor.0.location().unwrap())?
.display(vt, &numbering)?;
- hidden += numbers + SpaceNode::new().pack();
+ hidden += numbers + SpaceElem::new().pack();
};
}
if !ancestors.is_empty() {
- seq.push(HideNode::new(hidden).pack());
- seq.push(SpaceNode::new().pack());
+ seq.push(HideElem::new(hidden).pack());
+ seq.push(SpaceElem::new().pack());
}
}
// Format the numbering.
let mut start = heading.body();
if let Some(numbering) = heading.numbering(StyleChain::default()) {
- let numbers = Counter::of(HeadingNode::id())
- .at(vt, stable_id)?
+ let numbers = Counter::of(HeadingElem::func())
+ .at(vt, location)?
.display(vt, &numbering)?;
- start = numbers + SpaceNode::new().pack() + start;
+ start = numbers + SpaceElem::new().pack() + start;
};
// Add the numbering and section name.
- seq.push(start.linked(Link::Node(stable_id)));
+ seq.push(start.linked(Destination::Location(location)));
// Add filler symbols between the section name and page number.
if let Some(filler) = self.fill(styles) {
- seq.push(SpaceNode::new().pack());
+ seq.push(SpaceElem::new().pack());
seq.push(
- BoxNode::new()
+ BoxElem::new()
.with_body(Some(filler.clone()))
.with_width(Fr::one().into())
.pack(),
);
- seq.push(SpaceNode::new().pack());
+ seq.push(SpaceElem::new().pack());
} else {
- seq.push(HNode::new(Fr::one().into()).pack());
+ seq.push(HElem::new(Fr::one().into()).pack());
}
// Add the page number and linebreak.
- let page = vt.introspector.page(stable_id);
- let end = TextNode::packed(eco_format!("{page}"));
- seq.push(end.linked(Link::Node(stable_id)));
- seq.push(LinebreakNode::new().pack());
+ let page = vt.introspector.page(location);
+ let end = TextElem::packed(eco_format!("{page}"));
+ seq.push(end.linked(Destination::Location(location)));
+ seq.push(LinebreakElem::new().pack());
ancestors.push(heading);
}
- seq.push(ParbreakNode::new().pack());
+ seq.push(ParbreakElem::new().pack());
Ok(Content::sequence(seq))
}
}
-impl LocalName for OutlineNode {
+impl LocalName for OutlineElem {
fn local_name(&self, lang: Lang) -> &'static str {
match lang {
Lang::GERMAN => "Inhaltsverzeichnis",
diff --git a/library/src/meta/query.rs b/library/src/meta/query.rs
index 23e310fe..94b25cbc 100644
--- a/library/src/meta/query.rs
+++ b/library/src/meta/query.rs
@@ -11,24 +11,24 @@ pub fn query(
target: Target,
/// The location.
#[external]
- location: StableId,
+ location: Location,
/// The location before which to query.
#[named]
#[external]
- before: StableId,
+ before: Location,
/// The location after which to query.
#[named]
#[external]
- after: StableId,
+ after: Location,
) -> Value {
let selector = target.0;
let introspector = vm.vt.introspector;
- let elements = if let Some(id) = args.named("before")? {
- introspector.query_before(selector, id)
- } else if let Some(id) = args.named("after")? {
- introspector.query_after(selector, id)
+ let elements = if let Some(location) = args.named("before")? {
+ introspector.query_before(selector, location)
+ } else if let Some(location) = args.named("after")? {
+ introspector.query_after(selector, location)
} else {
- let _: StableId = args.expect("id")?;
+ let _: Location = args.expect("location")?;
introspector.query(selector)
};
elements.into()
@@ -40,15 +40,11 @@ struct Target(Selector);
cast_from_value! {
Target,
label: Label => Self(Selector::Label(label)),
- func: Func => {
- let Some(id) = func.id() else {
- return Err("this function is not selectable".into());
- };
-
- if !Content::new(id).can::<dyn Locatable>() {
- Err(eco_format!("cannot query for {}s", id.name))?;
+ element: ElemFunc => {
+ if !Content::new(element).can::<dyn Locatable>() {
+ Err(eco_format!("cannot query for {}s", element.name()))?;
}
- Self(Selector::Node(id, None))
+ Self(Selector::Elem(element, None))
}
}
diff --git a/library/src/meta/reference.rs b/library/src/meta/reference.rs
index 000080d8..6e794d2d 100644
--- a/library/src/meta/reference.rs
+++ b/library/src/meta/reference.rs
@@ -1,6 +1,6 @@
-use super::{BibliographyNode, CiteNode, Counter, LocalName, Numbering};
+use super::{BibliographyElem, CiteElem, Counter, LocalName, Numbering};
use crate::prelude::*;
-use crate::text::TextNode;
+use crate::text::TextElem;
/// A reference to a label.
///
@@ -35,8 +35,8 @@ use crate::text::TextNode;
///
/// Display: Reference
/// Category: meta
-#[node(Locatable, Show)]
-pub struct RefNode {
+#[element(Locatable, Show)]
+pub struct RefElem {
/// The target label that should be referenced.
#[required]
pub target: Label,
@@ -63,7 +63,7 @@ pub struct RefNode {
pub supplement: Smart<Option<Supplement>>,
}
-impl Show for RefNode {
+impl Show for RefElem {
fn show(&self, vt: &mut Vt, styles: StyleChain) -> SourceResult<Content> {
if !vt.introspector.init() {
return Ok(Content::empty());
@@ -72,7 +72,7 @@ impl Show for RefNode {
let target = self.target();
let matches = vt.introspector.query(Selector::Label(self.target()));
- if BibliographyNode::has(vt, &target.0) {
+ if BibliographyElem::has(vt, &target.0) {
if !matches.is_empty() {
bail!(self.span(), "label occurs in the document and its bibliography");
}
@@ -80,7 +80,7 @@ impl Show for RefNode {
return self.to_citation(styles).show(vt, styles);
}
- let [node] = matches.as_slice() else {
+ let [elem] = matches.as_slice() else {
bail!(self.span(), if matches.is_empty() {
"label does not exist in the document"
} else {
@@ -88,50 +88,50 @@ impl Show for RefNode {
});
};
- if !node.can::<dyn Locatable>() {
- bail!(self.span(), "cannot reference {}", node.id().name);
+ if !elem.can::<dyn Locatable>() {
+ bail!(self.span(), "cannot reference {}", elem.func().name());
}
let supplement = self.supplement(styles);
let mut supplement = match supplement {
- Smart::Auto => node
+ Smart::Auto => elem
.with::<dyn LocalName>()
- .map(|node| node.local_name(TextNode::lang_in(styles)))
- .map(TextNode::packed)
+ .map(|elem| elem.local_name(TextElem::lang_in(styles)))
+ .map(TextElem::packed)
.unwrap_or_default(),
Smart::Custom(None) => Content::empty(),
Smart::Custom(Some(Supplement::Content(content))) => content.clone(),
Smart::Custom(Some(Supplement::Func(func))) => {
- func.call_vt(vt, [node.clone().into()])?.display()
+ func.call_vt(vt, [elem.clone().into()])?.display()
}
};
if !supplement.is_empty() {
- supplement += TextNode::packed('\u{a0}');
+ supplement += TextElem::packed('\u{a0}');
}
- let Some(numbering) = node.cast_field::<Numbering>("numbering") else {
+ let Some(numbering) = elem.cast_field::<Numbering>("numbering") else {
bail!(self.span(), "only numbered elements can be referenced");
};
- let numbers = Counter::of(node.id())
- .at(vt, node.stable_id().unwrap())?
+ let numbers = Counter::of(elem.func())
+ .at(vt, elem.location().unwrap())?
.display(vt, &numbering.trimmed())?;
- Ok((supplement + numbers).linked(Link::Node(node.stable_id().unwrap())))
+ Ok((supplement + numbers).linked(Destination::Location(elem.location().unwrap())))
}
}
-impl RefNode {
+impl RefElem {
/// Turn the rference into a citation.
- pub fn to_citation(&self, styles: StyleChain) -> CiteNode {
- let mut node = CiteNode::new(vec![self.target().0]);
- node.push_supplement(match self.supplement(styles) {
+ pub fn to_citation(&self, styles: StyleChain) -> CiteElem {
+ let mut elem = CiteElem::new(vec![self.target().0]);
+ elem.push_supplement(match self.supplement(styles) {
Smart::Custom(Some(Supplement::Content(content))) => Some(content),
_ => None,
});
- node.0.set_stable_id(self.0.stable_id().unwrap());
- node
+ elem.0.set_location(self.0.location().unwrap());
+ elem
}
}
diff --git a/library/src/meta/state.rs b/library/src/meta/state.rs
index b19a2671..090f1ccf 100644
--- a/library/src/meta/state.rs
+++ b/library/src/meta/state.rs
@@ -52,25 +52,25 @@ impl State {
/// Display the current value of the state.
pub fn display(self, func: Option<Func>) -> Content {
- DisplayNode::new(self, func).pack()
+ DisplayElem::new(self, func).pack()
}
/// Get the value of the state at the given location.
- pub fn at(self, vt: &mut Vt, id: StableId) -> SourceResult<Value> {
+ pub fn at(self, vt: &mut Vt, location: Location) -> SourceResult<Value> {
let sequence = self.sequence(vt)?;
- let offset = vt.introspector.query_before(self.selector(), id).len();
+ let offset = vt.introspector.query_before(self.selector(), location).len();
Ok(sequence[offset].clone())
}
/// Get the value of the state at the final location.
- pub fn final_(self, vt: &mut Vt, _: StableId) -> SourceResult<Value> {
+ pub fn final_(self, vt: &mut Vt, _: Location) -> SourceResult<Value> {
let sequence = self.sequence(vt)?;
Ok(sequence.last().unwrap().clone())
}
/// Produce content that performs a state update.
pub fn update(self, update: StateUpdate) -> Content {
- UpdateNode::new(self, update).pack()
+ UpdateElem::new(self, update).pack()
}
/// Produce the whole sequence of states.
@@ -99,9 +99,9 @@ impl State {
let mut state = self.init.clone();
let mut stops = eco_vec![state.clone()];
- for node in introspector.query(self.selector()) {
- let node = node.to::<UpdateNode>().unwrap();
- match node.update() {
+ for elem in introspector.query(self.selector()) {
+ let elem = elem.to::<UpdateElem>().unwrap();
+ match elem.update() {
StateUpdate::Set(value) => state = value,
StateUpdate::Func(func) => state = func.call_vt(&mut vt, [state])?,
}
@@ -113,10 +113,7 @@ impl State {
/// The selector for this state's updates.
fn selector(&self) -> Selector {
- Selector::Node(
- NodeId::of::<UpdateNode>(),
- Some(dict! { "state" => self.clone() }),
- )
+ Selector::Elem(UpdateElem::func(), Some(dict! { "state" => self.clone() }))
}
}
@@ -159,8 +156,8 @@ cast_from_value! {
///
/// Display: State
/// Category: special
-#[node(Locatable, Show)]
-struct DisplayNode {
+#[element(Locatable, Show)]
+struct DisplayElem {
/// The state.
#[required]
state: State,
@@ -170,10 +167,10 @@ struct DisplayNode {
func: Option<Func>,
}
-impl Show for DisplayNode {
+impl Show for DisplayElem {
fn show(&self, vt: &mut Vt, _: StyleChain) -> SourceResult<Content> {
- let id = self.0.stable_id().unwrap();
- let value = self.state().at(vt, id)?;
+ let location = self.0.location().unwrap();
+ let value = self.state().at(vt, location)?;
Ok(match self.func() {
Some(func) => func.call_vt(vt, [value])?.display(),
None => value.display(),
@@ -185,8 +182,8 @@ impl Show for DisplayNode {
///
/// Display: State
/// Category: special
-#[node(Locatable, Show)]
-struct UpdateNode {
+#[element(Locatable, Show)]
+struct UpdateElem {
/// The state.
#[required]
state: State,
@@ -196,7 +193,7 @@ struct UpdateNode {
update: StateUpdate,
}
-impl Show for UpdateNode {
+impl Show for UpdateElem {
fn show(&self, _: &mut Vt, _: StyleChain) -> SourceResult<Content> {
Ok(Content::empty())
}
diff --git a/library/src/prelude.rs b/library/src/prelude.rs
index 55e5f17b..4c83cf31 100644
--- a/library/src/prelude.rs
+++ b/library/src/prelude.rs
@@ -22,9 +22,9 @@ pub use typst::eval::{
pub use typst::geom::*;
#[doc(no_inline)]
pub use typst::model::{
- node, Behave, Behaviour, Construct, Content, Finalize, Fold, Introspector, Label,
- Locatable, MetaNode, Node, NodeId, Resolve, Selector, Set, Show, StabilityProvider,
- StableId, StyleChain, StyleMap, StyleVec, Synthesize, Unlabellable, Vt,
+ element, Behave, Behaviour, Construct, Content, ElemFunc, Element, Finalize, Fold,
+ Introspector, Label, Locatable, Location, MetaElem, Resolve, Selector, Set, Show,
+ StabilityProvider, StyleChain, StyleVec, Styles, Synthesize, Unlabellable, Vt,
};
#[doc(no_inline)]
pub use typst::syntax::{Span, Spanned};
@@ -36,4 +36,4 @@ pub use typst::World;
#[doc(no_inline)]
pub use crate::layout::{Fragment, Layout, Regions};
#[doc(no_inline)]
-pub use crate::shared::{ContentExt, StyleMapExt};
+pub use crate::shared::{ContentExt, StylesExt};
diff --git a/library/src/shared/behave.rs b/library/src/shared/behave.rs
index eff41c0b..6a1aa127 100644
--- a/library/src/shared/behave.rs
+++ b/library/src/shared/behave.rs
@@ -1,14 +1,15 @@
-//! Node interaction.
+//! Element interaction.
use typst::model::{Behave, Behaviour, Content, StyleChain, StyleVec, StyleVecBuilder};
-/// A wrapper around a [`StyleVecBuilder`] that allows items to interact.
+/// A wrapper around a [`StyleVecBuilder`] that allows elements to interact.
#[derive(Debug)]
pub struct BehavedBuilder<'a> {
/// The internal builder.
builder: StyleVecBuilder<'a, Content>,
- /// Staged weak and ignorant items that we can't yet commit to the builder.
- /// The option is `Some(_)` for weak items and `None` for ignorant items.
+ /// Staged weak and ignorant elements that we can't yet commit to the
+ /// builder. The option is `Some(_)` for weak elements and `None` for
+ /// ignorant elements.
staged: Vec<(Content, Behaviour, StyleChain<'a>)>,
/// What the last non-ignorant item was.
last: Behaviour,
@@ -29,7 +30,7 @@ impl<'a> BehavedBuilder<'a> {
self.builder.is_empty() && self.staged.is_empty()
}
- /// Whether the builder is empty except for some weak items that will
+ /// Whether the builder is empty except for some weak elements that will
/// probably collapse.
pub fn is_basically_empty(&self) -> bool {
self.builder.is_empty()
@@ -40,15 +41,15 @@ impl<'a> BehavedBuilder<'a> {
}
/// Push an item into the sequence.
- pub fn push(&mut self, item: Content, styles: StyleChain<'a>) {
- let interaction = item
+ pub fn push(&mut self, elem: Content, styles: StyleChain<'a>) {
+ let interaction = elem
.with::<dyn Behave>()
.map_or(Behaviour::Supportive, Behave::behaviour);
match interaction {
Behaviour::Weak(level) => {
if matches!(self.last, Behaviour::Weak(_)) {
- let item = item.with::<dyn Behave>().unwrap();
+ let item = elem.with::<dyn Behave>().unwrap();
let i = self.staged.iter().position(|prev| {
let Behaviour::Weak(prev_level) = prev.1 else { return false };
level < prev_level
@@ -59,29 +60,29 @@ impl<'a> BehavedBuilder<'a> {
}
if self.last != Behaviour::Destructive {
- self.staged.push((item, interaction, styles));
+ self.staged.push((elem, interaction, styles));
self.last = interaction;
}
}
Behaviour::Supportive => {
self.flush(true);
- self.builder.push(item, styles);
+ self.builder.push(elem, styles);
self.last = interaction;
}
Behaviour::Destructive => {
self.flush(false);
- self.builder.push(item, styles);
+ self.builder.push(elem, styles);
self.last = interaction;
}
Behaviour::Ignorant => {
- self.staged.push((item, interaction, styles));
+ self.staged.push((elem, interaction, styles));
}
}
}
- /// Iterate over the contained items.
- pub fn items(&self) -> impl DoubleEndedIterator<Item = &Content> {
- self.builder.items().chain(self.staged.iter().map(|(item, ..)| item))
+ /// Iterate over the contained elements.
+ pub fn elems(&self) -> impl DoubleEndedIterator<Item = &Content> {
+ self.builder.elems().chain(self.staged.iter().map(|(item, ..)| item))
}
/// Return the finish style vec and the common prefix chain.
@@ -90,7 +91,7 @@ impl<'a> BehavedBuilder<'a> {
self.builder.finish()
}
- /// Push the staged items, filtering out weak items if `supportive` is
+ /// Push the staged elements, filtering out weak elements if `supportive` is
/// false.
fn flush(&mut self, supportive: bool) {
for (item, interaction, styles) in self.staged.drain(..) {
diff --git a/library/src/shared/ext.rs b/library/src/shared/ext.rs
index 14674c9d..72a82749 100644
--- a/library/src/shared/ext.rs
+++ b/library/src/shared/ext.rs
@@ -1,8 +1,8 @@
//! Extension traits.
-use crate::layout::{AlignNode, MoveNode, PadNode};
+use crate::layout::{AlignElem, MoveElem, PadElem};
use crate::prelude::*;
-use crate::text::{EmphNode, FontFamily, FontList, StrongNode, TextNode, UnderlineNode};
+use crate::text::{EmphElem, FontFamily, FontList, StrongElem, TextElem, UnderlineElem};
/// Additional methods on content.
pub trait ContentExt {
@@ -16,7 +16,7 @@ pub trait ContentExt {
fn underlined(self) -> Self;
/// Link the content somewhere.
- fn linked(self, link: Link) -> Self;
+ fn linked(self, dest: Destination) -> Self;
/// Set alignments for this content.
fn aligned(self, aligns: Axes<Option<GenAlign>>) -> Self;
@@ -30,27 +30,27 @@ pub trait ContentExt {
impl ContentExt for Content {
fn strong(self) -> Self {
- StrongNode::new(self).pack()
+ StrongElem::new(self).pack()
}
fn emph(self) -> Self {
- EmphNode::new(self).pack()
+ EmphElem::new(self).pack()
}
fn underlined(self) -> Self {
- UnderlineNode::new(self).pack()
+ UnderlineElem::new(self).pack()
}
- fn linked(self, link: Link) -> Self {
- self.styled(MetaNode::set_data(vec![Meta::Link(link)]))
+ fn linked(self, dest: Destination) -> Self {
+ self.styled(MetaElem::set_data(vec![Meta::Link(dest)]))
}
fn aligned(self, aligns: Axes<Option<GenAlign>>) -> Self {
- self.styled(AlignNode::set_alignment(aligns))
+ self.styled(AlignElem::set_alignment(aligns))
}
fn padded(self, padding: Sides<Rel<Length>>) -> Self {
- PadNode::new(self)
+ PadElem::new(self)
.with_left(padding.left)
.with_top(padding.top)
.with_right(padding.right)
@@ -59,22 +59,22 @@ impl ContentExt for Content {
}
fn moved(self, delta: Axes<Rel<Length>>) -> Self {
- MoveNode::new(self).with_dx(delta.x).with_dy(delta.y).pack()
+ MoveElem::new(self).with_dx(delta.x).with_dy(delta.y).pack()
}
}
-/// Additional methods for style maps.
-pub trait StyleMapExt {
+/// Additional methods for style lists.
+pub trait StylesExt {
/// Set a font family composed of a preferred family and existing families
/// from a style chain.
fn set_family(&mut self, preferred: FontFamily, existing: StyleChain);
}
-impl StyleMapExt for StyleMap {
+impl StylesExt for Styles {
fn set_family(&mut self, preferred: FontFamily, existing: StyleChain) {
- self.set(TextNode::set_font(FontList(
+ self.set(TextElem::set_font(FontList(
std::iter::once(preferred)
- .chain(TextNode::font_in(existing))
+ .chain(TextElem::font_in(existing))
.collect(),
)));
}
diff --git a/library/src/symbols/emoji.rs b/library/src/symbols/emoji.rs
index 07c7004b..5db3a799 100644
--- a/library/src/symbols/emoji.rs
+++ b/library/src/symbols/emoji.rs
@@ -993,7 +993,7 @@ const EMOJI: &[(&'static str, Symbol)] = symbols! {
piano: '🎹',
pick: '⛏',
pie: '🥧',
- pig: ['🐖', face: '🐷', node: '🐽'],
+ pig: ['🐖', face: '🐷', nose: '🐽'],
pill: '💊',
pin: ['📌', round: '📍'],
pinata: '🪅',
diff --git a/library/src/text/deco.rs b/library/src/text/deco.rs
index a29564f3..90a6ca85 100644
--- a/library/src/text/deco.rs
+++ b/library/src/text/deco.rs
@@ -1,7 +1,7 @@
use kurbo::{BezPath, Line, ParamCurve};
use ttf_parser::{GlyphId, OutlineBuilder};
-use super::TextNode;
+use super::TextElem;
use crate::prelude::*;
/// Underline text.
@@ -13,8 +13,8 @@ use crate::prelude::*;
///
/// Display: Underline
/// Category: text
-#[node(Show)]
-pub struct UnderlineNode {
+#[element(Show)]
+pub struct UnderlineElem {
/// How to stroke the line. The text color and thickness are read from the
/// font tables if `{auto}`.
///
@@ -65,9 +65,9 @@ pub struct UnderlineNode {
pub body: Content,
}
-impl Show for UnderlineNode {
+impl Show for UnderlineElem {
fn show(&self, _: &mut Vt, styles: StyleChain) -> SourceResult<Content> {
- Ok(self.body().styled(TextNode::set_deco(Decoration {
+ Ok(self.body().styled(TextElem::set_deco(Decoration {
line: DecoLine::Underline,
stroke: self.stroke(styles).unwrap_or_default(),
offset: self.offset(styles),
@@ -86,8 +86,8 @@ impl Show for UnderlineNode {
///
/// Display: Overline
/// Category: text
-#[node(Show)]
-pub struct OverlineNode {
+#[element(Show)]
+pub struct OverlineElem {
/// How to stroke the line. The text color and thickness are read from the
/// font tables if `{auto}`.
///
@@ -144,9 +144,9 @@ pub struct OverlineNode {
pub body: Content,
}
-impl Show for OverlineNode {
+impl Show for OverlineElem {
fn show(&self, _: &mut Vt, styles: StyleChain) -> SourceResult<Content> {
- Ok(self.body().styled(TextNode::set_deco(Decoration {
+ Ok(self.body().styled(TextElem::set_deco(Decoration {
line: DecoLine::Overline,
stroke: self.stroke(styles).unwrap_or_default(),
offset: self.offset(styles),
@@ -165,8 +165,8 @@ impl Show for OverlineNode {
///
/// Display: Strikethrough
/// Category: text
-#[node(Show)]
-pub struct StrikeNode {
+#[element(Show)]
+pub struct StrikeElem {
/// How to stroke the line. The text color and thickness are read from the
/// font tables if `{auto}`.
///
@@ -208,9 +208,9 @@ pub struct StrikeNode {
pub body: Content,
}
-impl Show for StrikeNode {
+impl Show for StrikeElem {
fn show(&self, _: &mut Vt, styles: StyleChain) -> SourceResult<Content> {
- Ok(self.body().styled(TextNode::set_deco(Decoration {
+ Ok(self.body().styled(TextElem::set_deco(Decoration {
line: DecoLine::Strikethrough,
stroke: self.stroke(styles).unwrap_or_default(),
offset: self.offset(styles),
@@ -255,7 +255,7 @@ pub enum DecoLine {
pub(super) fn decorate(
frame: &mut Frame,
deco: &Decoration,
- text: &Text,
+ text: &TextItem,
shift: Abs,
pos: Point,
width: Abs,
@@ -285,7 +285,7 @@ pub(super) fn decorate(
if target.x >= min_width || !deco.evade {
let shape = Geometry::Line(target).stroked(stroke);
- frame.push(origin, Element::Shape(shape, Span::detached()));
+ frame.push(origin, FrameItem::Shape(shape, Span::detached()));
}
};
diff --git a/library/src/text/misc.rs b/library/src/text/misc.rs
index 5a5c8514..e1d9c0f2 100644
--- a/library/src/text/misc.rs
+++ b/library/src/text/misc.rs
@@ -1,20 +1,20 @@
-use super::TextNode;
+use super::TextElem;
use crate::prelude::*;
/// A text space.
///
/// Display: Space
/// Category: text
-#[node(Unlabellable, Behave)]
-pub struct SpaceNode {}
+#[element(Unlabellable, Behave)]
+pub struct SpaceElem {}
-impl Behave for SpaceNode {
+impl Behave for SpaceElem {
fn behaviour(&self) -> Behaviour {
Behaviour::Weak(2)
}
}
-impl Unlabellable for SpaceNode {}
+impl Unlabellable for SpaceElem {}
/// Inserts a line break.
///
@@ -36,8 +36,8 @@ impl Unlabellable for SpaceNode {}
///
/// Display: Line Break
/// Category: text
-#[node(Behave)]
-pub struct LinebreakNode {
+#[element(Behave)]
+pub struct LinebreakElem {
/// Whether to justify the line before the break.
///
/// This is useful if you found a better line break opportunity in your
@@ -55,7 +55,7 @@ pub struct LinebreakNode {
pub justify: bool,
}
-impl Behave for LinebreakNode {
+impl Behave for LinebreakElem {
fn behaviour(&self) -> Behaviour {
Behaviour::Destructive
}
@@ -82,8 +82,8 @@ impl Behave for LinebreakNode {
///
/// Display: Strong Emphasis
/// Category: text
-#[node(Show)]
-pub struct StrongNode {
+#[element(Show)]
+pub struct StrongElem {
/// The delta to apply on the font weight.
///
/// ```example
@@ -98,9 +98,9 @@ pub struct StrongNode {
pub body: Content,
}
-impl Show for StrongNode {
+impl Show for StrongElem {
fn show(&self, _: &mut Vt, styles: StyleChain) -> SourceResult<Content> {
- Ok(self.body().styled(TextNode::set_delta(Delta(self.delta(styles)))))
+ Ok(self.body().styled(TextElem::set_delta(Delta(self.delta(styles)))))
}
}
@@ -151,16 +151,16 @@ impl Fold for Delta {
///
/// Display: Emphasis
/// Category: text
-#[node(Show)]
-pub struct EmphNode {
+#[element(Show)]
+pub struct EmphElem {
/// The content to emphasize.
#[required]
pub body: Content,
}
-impl Show for EmphNode {
+impl Show for EmphElem {
fn show(&self, _: &mut Vt, _: StyleChain) -> SourceResult<Content> {
- Ok(self.body().styled(TextNode::set_emph(Toggle)))
+ Ok(self.body().styled(TextElem::set_emph(Toggle)))
}
}
@@ -229,7 +229,7 @@ pub fn upper(
fn case(text: ToCase, case: Case) -> Value {
match text {
ToCase::Str(v) => Value::Str(case.apply(&v).into()),
- ToCase::Content(v) => Value::Content(v.styled(TextNode::set_case(Some(case)))),
+ ToCase::Content(v) => Value::Content(v.styled(TextElem::set_case(Some(case)))),
}
}
@@ -295,7 +295,7 @@ pub fn smallcaps(
/// The text to display to small capitals.
body: Content,
) -> Value {
- Value::Content(body.styled(TextNode::set_smallcaps(true)))
+ Value::Content(body.styled(TextElem::set_smallcaps(true)))
}
/// Create blind text.
diff --git a/library/src/text/mod.rs b/library/src/text/mod.rs
index 845ffe29..16268aad 100644
--- a/library/src/text/mod.rs
+++ b/library/src/text/mod.rs
@@ -19,7 +19,7 @@ use std::borrow::Cow;
use rustybuzz::Tag;
use typst::font::{FontMetrics, FontStretch, FontStyle, FontWeight, VerticalFontMetric};
-use crate::layout::ParNode;
+use crate::layout::ParElem;
use crate::prelude::*;
/// Customize the look and layout of text in a variety of ways.
@@ -40,8 +40,8 @@ use crate::prelude::*;
///
/// Display: Text
/// Category: text
-#[node(Construct)]
-pub struct TextNode {
+#[element(Construct)]
+pub struct TextElem {
/// A prioritized sequence of font families.
///
/// When processing text, Typst tries all specified font families in order
@@ -291,7 +291,7 @@ pub struct TextNode {
/// هذا عربي.
/// ```
#[resolve]
- pub dir: HorizontalDir,
+ pub dir: TextDir,
/// Whether to hyphenate text to improve line breaking. When `{auto}`, text
/// will be hyphenated if and only if justification is enabled.
@@ -479,16 +479,16 @@ pub struct TextNode {
pub smallcaps: bool,
}
-impl TextNode {
- /// Create a new packed text node.
+impl TextElem {
+ /// Create a new packed text element.
pub fn packed(text: impl Into<EcoString>) -> Content {
Self::new(text.into()).pack()
}
}
-impl Construct for TextNode {
- fn construct(_: &Vm, args: &mut Args) -> SourceResult<Content> {
- // The text constructor is special: It doesn't create a text node.
+impl Construct for TextElem {
+ fn construct(_: &mut Vm, args: &mut Args) -> SourceResult<Content> {
+ // The text constructor is special: It doesn't create a text element.
// Instead, it leaves the passed argument structurally unchanged, but
// styles all text in it.
let styles = Self::set(args)?;
@@ -606,28 +606,28 @@ cast_to_value! {
/// The direction of text and inline objects in their line.
#[derive(Debug, Default, Copy, Clone, Eq, PartialEq, Hash)]
-pub struct HorizontalDir(pub Smart<Dir>);
+pub struct TextDir(pub Smart<Dir>);
cast_from_value! {
- HorizontalDir,
+ TextDir,
v: Smart<Dir> => {
if v.map_or(false, |dir| dir.axis() == Axis::Y) {
- Err("must be horizontal")?;
+ Err("text direction must be horizontal")?;
}
Self(v)
},
}
cast_to_value! {
- v: HorizontalDir => v.0.into()
+ v: TextDir => v.0.into()
}
-impl Resolve for HorizontalDir {
+impl Resolve for TextDir {
type Output = Dir;
fn resolve(self, styles: StyleChain) -> Self::Output {
match self.0 {
- Smart::Auto => TextNode::lang_in(styles).dir(),
+ Smart::Auto => TextElem::lang_in(styles).dir(),
Smart::Custom(dir) => dir,
}
}
@@ -651,7 +651,7 @@ impl Resolve for Hyphenate {
fn resolve(self, styles: StyleChain) -> Self::Output {
match self.0 {
- Smart::Auto => ParNode::justify_in(styles),
+ Smart::Auto => ParElem::justify_in(styles),
Smart::Custom(v) => v,
}
}
@@ -677,7 +677,7 @@ cast_from_value! {
StylisticSet,
v: i64 => match v {
1 ..= 20 => Self::new(v as u8),
- _ => Err("must be between 1 and 20")?,
+ _ => Err("stylistic set must be between 1 and 20")?,
},
}
diff --git a/library/src/text/quotes.rs b/library/src/text/quotes.rs
index 863cc3bd..be923304 100644
--- a/library/src/text/quotes.rs
+++ b/library/src/text/quotes.rs
@@ -24,8 +24,8 @@ use crate::prelude::*;
///
/// Display: Smart Quote
/// Category: text
-#[node]
-pub struct SmartQuoteNode {
+#[element]
+pub struct SmartQuoteElem {
/// Whether this should be a double quote.
#[default(true)]
pub double: bool,
diff --git a/library/src/text/raw.rs b/library/src/text/raw.rs
index b6cc0d3d..d24254ed 100644
--- a/library/src/text/raw.rs
+++ b/library/src/text/raw.rs
@@ -3,9 +3,9 @@ use syntect::highlighting as synt;
use typst::syntax::{self, LinkedNode};
use super::{
- FontFamily, FontList, Hyphenate, LinebreakNode, SmartQuoteNode, TextNode, TextSize,
+ FontFamily, FontList, Hyphenate, LinebreakElem, SmartQuoteElem, TextElem, TextSize,
};
-use crate::layout::BlockNode;
+use crate::layout::BlockElem;
use crate::prelude::*;
/// Raw text with optional syntax highlighting.
@@ -35,8 +35,8 @@ use crate::prelude::*;
///
/// Display: Raw Text / Code
/// Category: text
-#[node(Synthesize, Show, Finalize)]
-pub struct RawNode {
+#[element(Synthesize, Show, Finalize)]
+pub struct RawElem {
/// The raw text.
///
/// You can also use raw blocks creatively to create custom syntaxes for
@@ -103,7 +103,7 @@ pub struct RawNode {
pub lang: Option<EcoString>,
}
-impl RawNode {
+impl RawElem {
/// The supported language names and tags.
pub fn languages() -> Vec<(&'static str, Vec<&'static str>)> {
SYNTAXES
@@ -120,13 +120,13 @@ impl RawNode {
}
}
-impl Synthesize for RawNode {
+impl Synthesize for RawElem {
fn synthesize(&mut self, _: &Vt, styles: StyleChain) {
self.push_lang(self.lang(styles));
}
}
-impl Show for RawNode {
+impl Show for RawElem {
fn show(&self, _: &mut Vt, styles: StyleChain) -> SourceResult<Content> {
let text = self.text();
let lang = self.lang(styles).as_ref().map(|s| s.to_lowercase());
@@ -162,7 +162,7 @@ impl Show for RawNode {
let mut highlighter = syntect::easy::HighlightLines::new(syntax, &THEME);
for (i, line) in text.lines().enumerate() {
if i != 0 {
- seq.push(LinebreakNode::new().pack());
+ seq.push(LinebreakElem::new().pack());
}
for (style, piece) in
@@ -174,26 +174,27 @@ impl Show for RawNode {
Content::sequence(seq)
} else {
- TextNode::packed(text)
+ TextElem::packed(text)
};
if self.block(styles) {
- realized = BlockNode::new().with_body(Some(realized)).pack();
+ realized = BlockElem::new().with_body(Some(realized)).pack();
}
Ok(realized)
}
}
-impl Finalize for RawNode {
+impl Finalize for RawElem {
fn finalize(&self, realized: Content, _: StyleChain) -> Content {
- let mut map = StyleMap::new();
- map.set(TextNode::set_overhang(false));
- map.set(TextNode::set_hyphenate(Hyphenate(Smart::Custom(false))));
- map.set(TextNode::set_size(TextSize(Em::new(0.8).into())));
- map.set(TextNode::set_font(FontList(vec![FontFamily::new("DejaVu Sans Mono")])));
- map.set(SmartQuoteNode::set_enabled(false));
- realized.styled_with_map(map)
+ let mut styles = Styles::new();
+ styles.set(TextElem::set_overhang(false));
+ styles.set(TextElem::set_hyphenate(Hyphenate(Smart::Custom(false))));
+ styles.set(TextElem::set_size(TextSize(Em::new(0.8).into())));
+ styles
+ .set(TextElem::set_font(FontList(vec![FontFamily::new("DejaVu Sans Mono")])));
+ styles.set(SmartQuoteElem::set_enabled(false));
+ realized.styled_with_map(styles)
}
}
@@ -224,11 +225,11 @@ fn highlight_themed<F>(
/// Style a piece of text with a syntect style.
fn styled(piece: &str, foreground: Paint, style: synt::Style) -> Content {
- let mut body = TextNode::packed(piece);
+ let mut body = TextElem::packed(piece);
let paint = to_typst(style.foreground).into();
if paint != foreground {
- body = body.styled(TextNode::set_fill(paint));
+ body = body.styled(TextElem::set_fill(paint));
}
if style.font_style.contains(synt::FontStyle::BOLD) {
diff --git a/library/src/text/shaping.rs b/library/src/text/shaping.rs
index 244e7afe..15fbcd3f 100644
--- a/library/src/text/shaping.rs
+++ b/library/src/text/shaping.rs
@@ -95,10 +95,10 @@ impl<'a> ShapedText<'a> {
let mut frame = Frame::new(size);
frame.set_baseline(top);
- let shift = TextNode::baseline_in(self.styles);
- let lang = TextNode::lang_in(self.styles);
- let decos = TextNode::deco_in(self.styles);
- let fill = TextNode::fill_in(self.styles);
+ let shift = TextElem::baseline_in(self.styles);
+ let lang = TextElem::lang_in(self.styles);
+ let decos = TextElem::deco_in(self.styles);
+ let fill = TextElem::fill_in(self.styles);
for ((font, y_offset), group) in
self.glyphs.as_ref().group_by_key(|g| (g.font.clone(), g.y_offset))
@@ -122,16 +122,16 @@ impl<'a> ShapedText<'a> {
})
.collect();
- let text = Text { font, size: self.size, lang, fill, glyphs };
- let text_layer = frame.layer();
- let width = text.width();
+ let item = TextItem { font, size: self.size, lang, fill, glyphs };
+ let layer = frame.layer();
+ let width = item.width();
// Apply line decorations.
for deco in &decos {
- decorate(&mut frame, deco, &text, shift, pos, width);
+ decorate(&mut frame, deco, &item, shift, pos, width);
}
- frame.insert(text_layer, pos, Element::Text(text));
+ frame.insert(layer, pos, FrameItem::Text(item));
offset += width;
}
@@ -146,8 +146,8 @@ impl<'a> ShapedText<'a> {
let mut top = Abs::zero();
let mut bottom = Abs::zero();
- let top_edge = TextNode::top_edge_in(self.styles);
- let bottom_edge = TextNode::bottom_edge_in(self.styles);
+ let top_edge = TextElem::top_edge_in(self.styles);
+ let bottom_edge = TextElem::bottom_edge_in(self.styles);
// Expand top and bottom by reading the font's vertical metrics.
let mut expand = |font: &Font| {
@@ -343,7 +343,7 @@ pub fn shape<'a>(
styles: StyleChain<'a>,
dir: Dir,
) -> ShapedText<'a> {
- let size = TextNode::size_in(styles);
+ let size = TextElem::size_in(styles);
let mut ctx = ShapingContext {
vt,
base,
@@ -354,7 +354,7 @@ pub fn shape<'a>(
styles,
variant: variant(styles),
tags: tags(styles),
- fallback: TextNode::fallback_in(styles),
+ fallback: TextElem::fallback_in(styles),
dir,
};
@@ -531,9 +531,9 @@ fn shape_tofus(ctx: &mut ShapingContext, base: usize, text: &str, font: Font) {
/// Apply tracking and spacing to the shaped glyphs.
fn track_and_space(ctx: &mut ShapingContext) {
- let tracking = Em::from_length(TextNode::tracking_in(ctx.styles), ctx.size);
+ let tracking = Em::from_length(TextElem::tracking_in(ctx.styles), ctx.size);
let spacing =
- TextNode::spacing_in(ctx.styles).map(|abs| Em::from_length(abs, ctx.size));
+ TextElem::spacing_in(ctx.styles).map(|abs| Em::from_length(abs, ctx.size));
let mut glyphs = ctx.glyphs.iter_mut().peekable();
while let Some(glyph) = glyphs.next() {
@@ -562,17 +562,17 @@ fn nbsp_delta(font: &Font) -> Option<Em> {
/// Resolve the font variant.
pub fn variant(styles: StyleChain) -> FontVariant {
let mut variant = FontVariant::new(
- TextNode::style_in(styles),
- TextNode::weight_in(styles),
- TextNode::stretch_in(styles),
+ TextElem::style_in(styles),
+ TextElem::weight_in(styles),
+ TextElem::stretch_in(styles),
);
- let delta = TextNode::delta_in(styles);
+ let delta = TextElem::delta_in(styles);
variant.weight = variant
.weight
.thicken(delta.clamp(i16::MIN as i64, i16::MAX as i64) as i16);
- if TextNode::emph_in(styles) {
+ if TextElem::emph_in(styles) {
variant.style = match variant.style {
FontStyle::Normal => FontStyle::Italic,
FontStyle::Italic => FontStyle::Normal,
@@ -593,8 +593,8 @@ pub fn families(styles: StyleChain) -> impl Iterator<Item = FontFamily> + Clone
"segoe ui emoji",
];
- let tail = if TextNode::fallback_in(styles) { FALLBACKS } else { &[] };
- TextNode::font_in(styles)
+ let tail = if TextElem::fallback_in(styles) { FALLBACKS } else { &[] };
+ TextElem::font_in(styles)
.into_iter()
.chain(tail.iter().copied().map(FontFamily::new))
}
@@ -607,59 +607,59 @@ fn tags(styles: StyleChain) -> Vec<Feature> {
};
// Features that are on by default in Harfbuzz are only added if disabled.
- if !TextNode::kerning_in(styles) {
+ if !TextElem::kerning_in(styles) {
feat(b"kern", 0);
}
// Features that are off by default in Harfbuzz are only added if enabled.
- if TextNode::smallcaps_in(styles) {
+ if TextElem::smallcaps_in(styles) {
feat(b"smcp", 1);
}
- if TextNode::alternates_in(styles) {
+ if TextElem::alternates_in(styles) {
feat(b"salt", 1);
}
let storage;
- if let Some(set) = TextNode::stylistic_set_in(styles) {
+ if let Some(set) = TextElem::stylistic_set_in(styles) {
storage = [b's', b's', b'0' + set.get() / 10, b'0' + set.get() % 10];
feat(&storage, 1);
}
- if !TextNode::ligatures_in(styles) {
+ if !TextElem::ligatures_in(styles) {
feat(b"liga", 0);
feat(b"clig", 0);
}
- if TextNode::discretionary_ligatures_in(styles) {
+ if TextElem::discretionary_ligatures_in(styles) {
feat(b"dlig", 1);
}
- if TextNode::historical_ligatures_in(styles) {
+ if TextElem::historical_ligatures_in(styles) {
feat(b"hilg", 1);
}
- match TextNode::number_type_in(styles) {
+ match TextElem::number_type_in(styles) {
Smart::Auto => {}
Smart::Custom(NumberType::Lining) => feat(b"lnum", 1),
Smart::Custom(NumberType::OldStyle) => feat(b"onum", 1),
}
- match TextNode::number_width_in(styles) {
+ match TextElem::number_width_in(styles) {
Smart::Auto => {}
Smart::Custom(NumberWidth::Proportional) => feat(b"pnum", 1),
Smart::Custom(NumberWidth::Tabular) => feat(b"tnum", 1),
}
- if TextNode::slashed_zero_in(styles) {
+ if TextElem::slashed_zero_in(styles) {
feat(b"zero", 1);
}
- if TextNode::fractions_in(styles) {
+ if TextElem::fractions_in(styles) {
feat(b"frac", 1);
}
- for (tag, value) in TextNode::features_in(styles).0 {
+ for (tag, value) in TextElem::features_in(styles).0 {
tags.push(Feature::new(tag, value, ..))
}
@@ -669,8 +669,8 @@ fn tags(styles: StyleChain) -> Vec<Feature> {
/// Process the language and and region of a style chain into a
/// rustybuzz-compatible BCP 47 language.
fn language(styles: StyleChain) -> rustybuzz::Language {
- let mut bcp: EcoString = TextNode::lang_in(styles).as_str().into();
- if let Some(region) = TextNode::region_in(styles) {
+ let mut bcp: EcoString = TextElem::lang_in(styles).as_str().into();
+ if let Some(region) = TextElem::region_in(styles) {
bcp.push('-');
bcp.push_str(region.as_str());
}
diff --git a/library/src/text/shift.rs b/library/src/text/shift.rs
index 74bb70c7..1bea3673 100644
--- a/library/src/text/shift.rs
+++ b/library/src/text/shift.rs
@@ -1,6 +1,4 @@
-use typst::model::SequenceNode;
-
-use super::{variant, SpaceNode, TextNode, TextSize};
+use super::{variant, SpaceElem, TextElem, TextSize};
use crate::prelude::*;
/// Set text in subscript.
@@ -14,8 +12,8 @@ use crate::prelude::*;
///
/// Display: Subscript
/// Category: text
-#[node(Show)]
-pub struct SubNode {
+#[element(Show)]
+pub struct SubElem {
/// Whether to prefer the dedicated subscript characters of the font.
///
/// If this is enabled, Typst first tries to transform the text to subscript
@@ -46,21 +44,21 @@ pub struct SubNode {
pub body: Content,
}
-impl Show for SubNode {
+impl Show for SubElem {
fn show(&self, vt: &mut Vt, styles: StyleChain) -> SourceResult<Content> {
let body = self.body();
let mut transformed = None;
if self.typographic(styles) {
if let Some(text) = search_text(&body, true) {
if is_shapable(vt, &text, styles) {
- transformed = Some(TextNode::packed(text));
+ transformed = Some(TextElem::packed(text));
}
}
};
Ok(transformed.unwrap_or_else(|| {
- body.styled(TextNode::set_baseline(self.baseline(styles)))
- .styled(TextNode::set_size(self.size(styles)))
+ body.styled(TextElem::set_baseline(self.baseline(styles)))
+ .styled(TextElem::set_size(self.size(styles)))
}))
}
}
@@ -76,8 +74,8 @@ impl Show for SubNode {
///
/// Display: Superscript
/// Category: text
-#[node(Show)]
-pub struct SuperNode {
+#[element(Show)]
+pub struct SuperElem {
/// Whether to prefer the dedicated superscript characters of the font.
///
/// If this is enabled, Typst first tries to transform the text to
@@ -108,35 +106,35 @@ pub struct SuperNode {
pub body: Content,
}
-impl Show for SuperNode {
+impl Show for SuperElem {
fn show(&self, vt: &mut Vt, styles: StyleChain) -> SourceResult<Content> {
let body = self.body();
let mut transformed = None;
if self.typographic(styles) {
if let Some(text) = search_text(&body, false) {
if is_shapable(vt, &text, styles) {
- transformed = Some(TextNode::packed(text));
+ transformed = Some(TextElem::packed(text));
}
}
};
Ok(transformed.unwrap_or_else(|| {
- body.styled(TextNode::set_baseline(self.baseline(styles)))
- .styled(TextNode::set_size(self.size(styles)))
+ body.styled(TextElem::set_baseline(self.baseline(styles)))
+ .styled(TextElem::set_size(self.size(styles)))
}))
}
}
/// Find and transform the text contained in `content` to the given script kind
-/// if and only if it only consists of `Text`, `Space`, and `Empty` leaf nodes.
+/// if and only if it only consists of `Text`, `Space`, and `Empty` leafs.
fn search_text(content: &Content, sub: bool) -> Option<EcoString> {
- if content.is::<SpaceNode>() {
+ if content.is::<SpaceElem>() {
Some(' '.into())
- } else if let Some(node) = content.to::<TextNode>() {
- convert_script(&node.text(), sub)
- } else if let Some(seq) = content.to::<SequenceNode>() {
+ } else if let Some(elem) = content.to::<TextElem>() {
+ convert_script(&elem.text(), sub)
+ } else if let Some(children) = content.to_sequence() {
let mut full = EcoString::new();
- for item in seq.children() {
+ for item in children {
match search_text(&item, sub) {
Some(text) => full.push_str(&text),
None => return None,
@@ -152,7 +150,7 @@ fn search_text(content: &Content, sub: bool) -> Option<EcoString> {
/// given string.
fn is_shapable(vt: &Vt, text: &str, styles: StyleChain) -> bool {
let world = vt.world;
- for family in TextNode::font_in(styles) {
+ for family in TextElem::font_in(styles) {
if let Some(font) = world
.book()
.select(family.as_str(), variant(styles))
diff --git a/library/src/visualize/image.rs b/library/src/visualize/image.rs
index c5016436..8a81a40e 100644
--- a/library/src/visualize/image.rs
+++ b/library/src/visualize/image.rs
@@ -22,8 +22,8 @@ use crate::prelude::*;
///
/// Display: Image
/// Category: visualize
-#[node(Layout)]
-pub struct ImageNode {
+#[element(Layout)]
+pub struct ImageElem {
/// Path to an image file.
#[required]
#[parse(
@@ -46,7 +46,7 @@ pub struct ImageNode {
pub fit: ImageFit,
}
-impl Layout for ImageNode {
+impl Layout for ImageElem {
fn layout(
&self,
vt: &mut Vt,
@@ -97,7 +97,7 @@ impl Layout for ImageNode {
// the frame to the target size, center aligning the image in the
// process.
let mut frame = Frame::new(fitted);
- frame.push(Point::zero(), Element::Image(image, fitted, self.span()));
+ frame.push(Point::zero(), FrameItem::Image(image, fitted, self.span()));
frame.resize(target, Align::CENTER_HORIZON);
// Create a clipping group if only part of the image should be visible.
diff --git a/library/src/visualize/line.rs b/library/src/visualize/line.rs
index 6614e3ee..0932a9f1 100644
--- a/library/src/visualize/line.rs
+++ b/library/src/visualize/line.rs
@@ -11,8 +11,8 @@ use crate::prelude::*;
///
/// Display: Line
/// Category: visualize
-#[node(Layout)]
-pub struct LineNode {
+#[element(Layout)]
+pub struct LineElem {
/// The start point of the line.
///
/// Must be an array of exactly two relative lengths.
@@ -49,7 +49,7 @@ pub struct LineNode {
pub stroke: PartialStroke,
}
-impl Layout for LineNode {
+impl Layout for LineElem {
fn layout(
&self,
_: &mut Vt,
@@ -76,7 +76,7 @@ impl Layout for LineNode {
let mut frame = Frame::new(target);
let shape = Geometry::Line(delta.to_point()).stroked(stroke);
- frame.push(start.to_point(), Element::Shape(shape, self.span()));
+ frame.push(start.to_point(), FrameItem::Shape(shape, self.span()));
Ok(Fragment::frame(frame))
}
}
diff --git a/library/src/visualize/shape.rs b/library/src/visualize/shape.rs
index 8aef3629..601f0d85 100644
--- a/library/src/visualize/shape.rs
+++ b/library/src/visualize/shape.rs
@@ -18,8 +18,8 @@ use crate::prelude::*;
///
/// Display: Rectangle
/// Category: visualize
-#[node(Layout)]
-pub struct RectNode {
+#[element(Layout)]
+pub struct RectElem {
/// The rectangle's width, relative to its parent container.
pub width: Smart<Rel<Length>>,
@@ -139,7 +139,7 @@ pub struct RectNode {
pub body: Option<Content>,
}
-impl Layout for RectNode {
+impl Layout for RectElem {
fn layout(
&self,
vt: &mut Vt,
@@ -179,8 +179,8 @@ impl Layout for RectNode {
///
/// Display: Square
/// Category: visualize
-#[node(Layout)]
-pub struct SquareNode {
+#[element(Layout)]
+pub struct SquareElem {
/// The square's side length. This is mutually exclusive with `width` and
/// `height`.
#[external]
@@ -249,7 +249,7 @@ pub struct SquareNode {
pub body: Option<Content>,
}
-impl Layout for SquareNode {
+impl Layout for SquareElem {
fn layout(
&self,
vt: &mut Vt,
@@ -290,8 +290,8 @@ impl Layout for SquareNode {
///
/// Display: Ellipse
/// Category: visualize
-#[node(Layout)]
-pub struct EllipseNode {
+#[element(Layout)]
+pub struct EllipseElem {
/// The ellipse's width, relative to its parent container.
pub width: Smart<Rel<Length>>,
@@ -331,7 +331,7 @@ pub struct EllipseNode {
pub body: Option<Content>,
}
-impl Layout for EllipseNode {
+impl Layout for EllipseElem {
fn layout(
&self,
vt: &mut Vt,
@@ -372,8 +372,8 @@ impl Layout for EllipseNode {
///
/// Display: Circle
/// Category: visualize
-#[node(Layout)]
-pub struct CircleNode {
+#[element(Layout)]
+pub struct CircleElem {
/// The circle's radius. This is mutually exclusive with `width` and
/// `height`.
#[external]
@@ -438,7 +438,7 @@ pub struct CircleNode {
pub body: Option<Content>,
}
-impl Layout for CircleNode {
+impl Layout for CircleElem {
fn layout(
&self,
vt: &mut Vt,
@@ -529,7 +529,7 @@ fn layout(
let size = frame.size() + outset.sum_by_axis();
let pos = Point::new(-outset.left, -outset.top);
let shape = ellipse(size, fill, stroke.left);
- frame.prepend(pos, Element::Shape(shape, span));
+ frame.prepend(pos, FrameItem::Shape(shape, span));
} else {
frame.fill_and_stroke(fill, stroke, outset, radius, span);
}