japanese_ruby_filter/
renderer.rs1use 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}