Skip to main content

japanese_ruby_filter/
renderer.rs

1use crate::Ruby;
2
3#[derive(Debug)]
4pub struct HtmlRenderer {
5    open_paren: String,
6    close_paren: String,
7}
8
9impl HtmlRenderer {
10    pub fn new() -> Self {
11        Self {
12            open_paren: "(".to_owned(),
13            close_paren: ")".to_owned(),
14        }
15    }
16
17    fn push_open_paren(&self, buffer: &mut String) {
18        buffer.push_str("<rp>");
19        buffer.push_str(&self.open_paren);
20        buffer.push_str("</rp>");
21    }
22
23    fn push_close_paren(&self, buffer: &mut String) {
24        buffer.push_str("<rp>");
25        buffer.push_str(&self.close_paren);
26        buffer.push_str("</rp>");
27    }
28
29    pub fn render(&self, ruby: &Ruby, buffer: &mut String) {
30        buffer.push_str("<ruby>");
31
32        for (rb, rt) in ruby.base().iter().zip(ruby.ruby()) {
33            buffer.push_str(rb);
34            self.push_open_paren(buffer);
35            buffer.push_str("<rt>");
36            buffer.push_str(rt);
37            buffer.push_str("</rt>");
38            self.push_close_paren(buffer);
39        }
40
41        buffer.push_str("</ruby>");
42    }
43}
44
45#[cfg(test)]
46mod test {
47    use super::*;
48
49    fn render_ruby(input: &Ruby) -> String {
50        let mut output = String::new();
51        HtmlRenderer::new().render(&input, &mut output);
52
53        output
54    }
55
56    #[test]
57    fn simple_ruby_to_html() {
58        let input = Ruby::from_str_vecs(vec!["漢", "字"], vec!["かん", "じ"]);
59        let expected = "<ruby>漢<rp>(</rp><rt>かん</rt><rp>)</rp>字<rp>(</rp><rt>じ</rt><rp>)</rp></ruby>";
60        assert_eq!(render_ruby(&input).as_str(), expected);
61    }
62
63    #[test]
64    fn one_group_ruby_to_html() {
65        let input = Ruby::from_str_vecs(vec!["境界"], vec!["フロンティア"]);
66        let expected = "<ruby>境界<rp>(</rp><rt>フロンティア</rt><rp>)</rp></ruby>";
67        assert_eq!(render_ruby(&input).as_str(), expected);
68    }
69}