rst_renderer/
html.rs
1mod elems_cats;
2mod multi;
3#[cfg(test)]
4pub mod tests;
5
6use std::io::Write;
7
8use anyhow::Error;
9
10use document_tree::{Document, HasChildren};
12
13pub fn render_html<W>(document: &Document, stream: W, standalone: bool) -> Result<(), Error>
18where
19 W: Write,
20{
21 let mut renderer = HTMLRenderer { stream, level: 0 };
22 if standalone {
23 document.render_html(&mut renderer)
24 } else {
25 document.children().render_html(&mut renderer)
26 }
27}
28
29fn escape_html(text: &str) -> String {
30 text.replace('&', "&")
31 .replace('<', "<")
32 .replace('>', ">")
33 .replace('"', """)
34}
35
36struct HTMLRenderer<W>
37where
38 W: Write,
39{
40 stream: W,
41 level: u8,
42}
43
44trait HTMLRender {
45 fn render_html<W>(&self, renderer: &mut HTMLRenderer<W>) -> Result<(), Error>
46 where
47 W: Write;
48}
49
50pub const FOOTNOTE_SYMBOLS: [char; 10] = ['*', '†', '‡', '§', '¶', '#', '♠', '♥', '♦', '♣'];
51
52pub fn footnote_symbol(n: usize) -> String {
53 FOOTNOTE_SYMBOLS
54 .iter()
55 .cycle()
56 .nth(n - 1)
57 .unwrap()
58 .to_string()
59}
60
61const HEAD: &str = r#"<head>
62<meta charset="utf-8">
63<meta name="color-scheme" content="dark light">
64<meta name="viewport" content="width=device-width, initial-scale=1">
65<style>
66@counter-style footnote-numeric {
67 system: numeric;
68 symbols: '0' '1' '2' '3' '4' '5' '6' '7' '8' '9';
69 prefix: '[';
70 suffix: '] ';
71}
72@counter-style footnote-symbolic {
73 system: symbolic;
74 symbols: '*' '†' '‡' '§' '¶' '#' '♠' '♥' '♦' '♣';
75 prefix: '';
76 suffix: ' ';
77}
78.footnote-reference:target,
79ol.footnotes > li:target {
80 background-color: hsl(60 100% 50% / 0.2);
81}
82ol.footnotes > li {
83 list-style-type: footnote-numeric;
84}
85ol.footnotes > li.symbol {
86 list-style-type: footnote-symbolic;
87}
88ol.footnotes > li > .backrefs {
89 float: left;
90 font-size: 0.8em;
91}
92</style>
93</head>"#;
94
95impl HTMLRender for Document {
96 fn render_html<W>(&self, renderer: &mut HTMLRenderer<W>) -> Result<(), Error>
97 where
98 W: Write,
99 {
100 writeln!(renderer.stream, "<!doctype html>\n<html>\n{HEAD}\n<body>")?;
101 self.children().render_html(renderer)?;
102 writeln!(renderer.stream, "</body>\n</html>")?;
103 Ok(())
104 }
105}
106
107