diff --git a/src/exec/context.rs b/src/exec/context.rs index 5ff55c00b..62f508802 100644 --- a/src/exec/context.rs +++ b/src/exec/context.rs @@ -9,6 +9,7 @@ use crate::geom::{ChildAlign, Dir, Gen, LayoutDirs, Length, Linear, Sides, Size} use crate::layout::{ Expansion, Node, NodePad, NodePages, NodePar, NodeSpacing, NodeStack, NodeText, Tree, }; +use crate::parse::is_newline; /// The context for execution. #[derive(Debug)] @@ -217,7 +218,7 @@ impl<'a> ExecContext<'a> { } } - /// Push a normal space. + /// Push a normal word space. pub fn push_space(&mut self) { let em = self.state.font.font_size(); self.push(NodeSpacing { @@ -226,10 +227,20 @@ impl<'a> ExecContext<'a> { }); } - /// Push a text node. - pub fn push_text(&mut self, text: impl Into) { - let node = self.make_text_node(text.into()); - self.push(node); + /// Push text into the context. + /// + /// The text is split into lines at newlines. + pub fn push_text(&mut self, text: &str) { + let mut newline = false; + for line in text.split_terminator(is_newline) { + if newline { + self.apply_linebreak(); + } + + let node = self.make_text_node(line.into()); + self.push(node); + newline = true; + } } /// Construct a text node from the given string based on the active text diff --git a/src/exec/mod.rs b/src/exec/mod.rs index 37c03cda0..ea2c90f43 100644 --- a/src/exec/mod.rs +++ b/src/exec/mod.rs @@ -139,17 +139,17 @@ impl Exec for Value { fn exec(&self, ctx: &mut ExecContext) { match self { Value::None => {} - Value::Int(v) => ctx.push_text(pretty(v)), - Value::Float(v) => ctx.push_text(pretty(v)), - Value::Str(s) => ctx.push_text(s), - Value::Template(template) => template.exec(ctx), + Value::Int(v) => ctx.push_text(&pretty(v)), + Value::Float(v) => ctx.push_text(&pretty(v)), + Value::Str(v) => ctx.push_text(v), + Value::Template(v) => v.exec(ctx), Value::Error => {} other => { // For values which can't be shown "naturally", we print // the representation in monospace. let prev = Rc::clone(&ctx.state.font.families); ctx.apply_monospace(); - ctx.push_text(pretty(other)); + ctx.push_text(&pretty(other)); ctx.state.font.families = prev; } } @@ -168,8 +168,8 @@ impl Exec for TemplateNode { fn exec(&self, ctx: &mut ExecContext) { match self { Self::Tree { tree, map } => tree.exec_with_map(ctx, &map), - Self::Str(s) => ctx.push_text(s), - Self::Func(func) => func.exec(ctx), + Self::Str(v) => ctx.push_text(v), + Self::Func(v) => v.exec(ctx), } } } diff --git a/tests/ref/expr/call-invalid.png b/tests/ref/expr/call-invalid.png index eee20e4d2..5d32238de 100644 Binary files a/tests/ref/expr/call-invalid.png and b/tests/ref/expr/call-invalid.png differ diff --git a/tests/ref/repr.png b/tests/ref/repr.png index 13ba62972..951506c4b 100644 Binary files a/tests/ref/repr.png and b/tests/ref/repr.png differ diff --git a/tests/typ/library/box.typ b/tests/typ/library/box.typ index 57763f12e..eff0be3d8 100644 --- a/tests/typ/library/box.typ +++ b/tests/typ/library/box.typ @@ -11,7 +11,7 @@ Sometimes there is no box. // Empty box with fixed width and height. #box(width: 6cm, height: 12pt, color: #CB4CED) -// Not visiblem, but creates a gap between the boxes above and below. +// Not visible, but creates a gap between the boxes above and below. #box(width: 2in, color: #ff0000) // These are in a row!