Skip to content

Commit b608561

Browse files
committed
Don't render raw() spans across newlines
1 parent 113b527 commit b608561

File tree

2 files changed

+68
-5
lines changed

2 files changed

+68
-5
lines changed

src/formatting/formatter.rs

Lines changed: 13 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -122,9 +122,11 @@ impl Formatter {
122122
}
123123

124124
fn indent(&mut self) {
125-
for _ in 0..self.nesting {
126-
self.buffer
127-
.push(' ');
125+
if self.nesting > 0 {
126+
// Flush any existing buffer before adding indentation
127+
self.flush_current();
128+
let spaces = " ".repeat(self.nesting as usize);
129+
self.append_fragment(Syntax::Indent, &spaces);
128130
}
129131
}
130132

@@ -217,8 +219,14 @@ impl Formatter {
217219
}
218220

219221
fn append_char(&mut self, c: char) {
220-
self.buffer
221-
.push(c);
222+
if c == '\n' {
223+
// Flush any existing buffer before adding newline
224+
self.flush_current();
225+
self.append_fragment(Syntax::Newline, "\n");
226+
} else {
227+
self.buffer
228+
.push(c);
229+
}
222230
}
223231

224232
fn is_empty(&self) -> bool {

src/formatting/renderer.rs

Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,8 @@ use std::borrow::Cow;
88
#[derive(Debug, Clone, Copy, PartialEq)]
99
pub enum Syntax {
1010
Neutral, // default
11+
Indent,
12+
Newline,
1113
Header,
1214
Declaration,
1315
Description,
@@ -56,6 +58,8 @@ impl Render for Terminal {
5658
fn render(&self, syntax: Syntax, content: &str) -> String {
5759
match syntax {
5860
Syntax::Neutral => content.to_string(),
61+
Syntax::Indent => content.to_string(),
62+
Syntax::Newline => "\n".to_string(),
5963
Syntax::Header => content
6064
.color(owo_colors::Rgb(0x75, 0x50, 0x7b))
6165
.to_string(),
@@ -151,6 +155,8 @@ impl Render for Typst {
151155
let content = escape_typst(content);
152156
match syntax {
153157
Syntax::Neutral => markup("", &content),
158+
Syntax::Indent => markup("", &content),
159+
Syntax::Newline => "\\\n".to_string(),
154160
Syntax::Header => markup("fill: rgb(0x75, 0x50, 0x7b)", &content),
155161
Syntax::Declaration => {
156162
markup("fill: rgb(0x34, 0x65, 0xa4), weight: \"bold\"", &content)
@@ -272,4 +278,53 @@ mod tests {
272278
let result = markup("", &content);
273279
assert_eq!(result, "#text(raw(\"escaped \"content\"\"))");
274280
}
281+
282+
#[test]
283+
fn typst_newline_and_indent_rendering() {
284+
let typst = Typst;
285+
286+
// Test that newlines are rendered as Typst line breaks
287+
let newline_result = typst.render(Syntax::Newline, "\n");
288+
assert_eq!(newline_result, "\\\n");
289+
290+
// Test that indentation is rendered without raw() wrapper
291+
let indent_result = typst.render(Syntax::Indent, " ");
292+
assert_eq!(indent_result, "#text(raw(\" \"))");
293+
294+
// Test that this is different from Neutral (which would wrap newlines in raw())
295+
let neutral_result = typst.render(Syntax::Neutral, "\n ");
296+
assert_eq!(neutral_result, "#text(raw(\"\n \"))");
297+
298+
// Verify the improvement: newlines no longer wrapped in raw()
299+
assert_ne!(newline_result, "#text(raw(\"\n\"))");
300+
}
301+
302+
#[test]
303+
fn verify_typst_fragments_usage() {
304+
// Simple test to verify that our new Syntax variants are used correctly
305+
let fragments = vec![
306+
(Syntax::Header, "% technique v1".to_string()),
307+
(Syntax::Newline, "\n".to_string()),
308+
(Syntax::Indent, " ".to_string()),
309+
(Syntax::StepItem, "1".to_string()),
310+
(Syntax::Neutral, ".".to_string()),
311+
(Syntax::Newline, "\n".to_string()),
312+
];
313+
314+
let typst = Typst;
315+
let mut output = String::new();
316+
317+
for (syntax, content) in fragments {
318+
let rendered = typst.render(syntax, &content);
319+
output.push_str(&rendered);
320+
}
321+
322+
// Verify improvements:
323+
// 1. Newlines are rendered as Typst line breaks
324+
assert!(output.contains("\\\n"));
325+
// 2. Indentation is wrapped in text() but not combined with newlines
326+
assert!(output.contains("#text(raw(\" \"))"));
327+
// 3. No raw() calls containing newlines
328+
assert!(!output.contains("raw(\"\n"));
329+
}
275330
}

0 commit comments

Comments
 (0)