Skip to main content

omni_dev/transcript/format/
txt.rs

1//! Plain-text renderer — cue text only, one cue per line, no timing.
2
3use crate::transcript::cue::Cue;
4
5/// Render `cues` as plain text: each cue's `text` followed by a newline,
6/// concatenated. Cues with embedded newlines retain them. Empty input
7/// yields `""`.
8pub fn render(cues: &[Cue]) -> String {
9    let mut out = String::new();
10    for cue in cues {
11        out.push_str(&cue.text);
12        out.push('\n');
13    }
14    out
15}
16
17#[cfg(test)]
18mod tests {
19    use super::*;
20
21    #[test]
22    fn empty_input_yields_empty_string() {
23        assert_eq!(render(&[]), "");
24    }
25
26    #[test]
27    fn single_cue() {
28        let out = render(&[Cue::new(0, 1_000, "hello")]);
29        assert_eq!(out, "hello\n");
30    }
31
32    #[test]
33    fn multiple_cues_joined_by_newline() {
34        let cues = vec![
35            Cue::new(0, 1_000, "one"),
36            Cue::new(1_000, 2_000, "two"),
37            Cue::new(2_000, 3_000, "three"),
38        ];
39        assert_eq!(render(&cues), "one\ntwo\nthree\n");
40    }
41
42    #[test]
43    fn embedded_newlines_preserved() {
44        let cues = vec![Cue::new(0, 1_000, "line one\nline two")];
45        assert_eq!(render(&cues), "line one\nline two\n");
46    }
47
48    #[test]
49    fn timing_is_omitted() {
50        let cues = vec![Cue::new(123_456, 789_012, "text")];
51        let out = render(&cues);
52        assert!(!out.contains("123"));
53        assert!(!out.contains("789"));
54        assert!(!out.contains(':'));
55        assert_eq!(out, "text\n");
56    }
57
58    #[test]
59    fn empty_cue_text_yields_blank_line() {
60        let cues = vec![Cue::new(0, 1_000, ""), Cue::new(1_000, 2_000, "x")];
61        assert_eq!(render(&cues), "\nx\n");
62    }
63
64    #[test]
65    fn output_always_ends_with_newline_when_nonempty() {
66        let cues = vec![Cue::new(0, 1_000, "hello")];
67        assert!(render(&cues).ends_with('\n'));
68    }
69}